home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / science / piw131.zip / MULTIIDW.CPP < prev    next >
C/C++ Source or Header  |  1994-07-29  |  77KB  |  2,521 lines

  1. // ------- MultiIDW.Cpp Multiple-precision integer decimal algorithms
  2. /*
  3.   Version= "Version 3.11, last revised: 1994-07-29, 0600 hours";
  4.   Author = "Copyright (c) 1981-1994 by author: Harry J. Smith,";
  5.   Address= "19628 Via Monte Dr., Saratoga, CA 95070.  All rights reserved.";
  6. */
  7.  
  8. #include "MultiIDW.h" // Multiple-precision integer decimal algorithms module
  9. #include <dos.h>      // gettime()
  10. #include <stdio.h>
  11. #include <conio.h>
  12. #include <math.h>
  13. #include <string.h>
  14. #include <alloc.h>
  15. #include <stdlib.h>
  16. #include <iostream.h>
  17.  
  18. #define max(a,b) (((a) > (b)) ? (a) : (b))
  19.  
  20. // char *cgets( char *str); // Not in Windows, use cin.get( St, 81);
  21.  
  22. // Developed in Turbo C++ 1.0.  Converted to Borland C++ 3.0 for Windows.
  23. // In Turbo C++ 1.0 the max odd integer to store in a float is
  24. // 2**24-1 = 167,77215; for a double is 2**53-1 = 9,00719,92547,40991
  25.  
  26. //  ostream& Out0 = NULL; // None of this worked???
  27. //  ostream_withassign OutP[2] = {cout, cLog};
  28. //  ostream OutP[2]; // OutP[i] << i << nL;  // a.WritLn( OutP[i]);
  29. //  OutP[0] = cout;
  30. //  ostream& Out = cout; // This worked
  31.  
  32. // ------- The following are set when the InitMulti is called
  33.   Mu2Digit Base;     // Radix of multi-precision numbers, 10**MuDMax
  34.   Mu1Digit MaxDigit; // Base - 1
  35.   Mu2Digit BaseSq;   // Base squared
  36.   Mu2Digit BSMB;     // (BaseSq - Base) for MuDiv and MuSqRt
  37.   RealPlus Pi;       // Pi
  38.   RealPlus Pi2;      // 2 * Pi
  39. // ------- The following can be tested by user
  40.   Bool MuErr;        // Boolean, True if multi-precision error occurred
  41.   Bool MuAbort;      // Boolean, True if Mu procedure interrupted by operator
  42.   Bool SoftAbort;    // Boolean, True if SoftAbort Flag set by operator
  43.   Bool KeyHit;       // Boolean. True if KeyPressed has been cleared
  44.   char KeyCh;        // Key input when KeyPressed was cleared
  45. // ------- The following can be changed by user
  46.   Bool Echo;         // 1 if in Echo output to log file mode, 0 otherwise
  47.   Bool MuDOnly;      // True if only raw digits of a number are to be output
  48.   int  MuDpG;        // Digits per group in number output display >= 1 or 0
  49.   int  MuLenD;       // Min length in digits to display length in digits
  50.   Bool MuErrRep;     // True if multi-precision error reports are desired
  51.   long MMax;         // Max number of super digits <= MuNMax
  52.   long TracN;        // Number if iterations of an innermost loop
  53.   long Trace;        // Number of "Digits" left to compute
  54.   long ShortN;       // If > 0 then Short format desired from x.Writ( Out)
  55.   Bool DiagOn;       // Diagnostics turned on
  56.   double TV0;        // Dos time value at time zero for diag
  57.   double TV1;        // Dos time value for delta time, TV2 - TV1
  58.   double TV2;        // Dos time value for total time, TV2 - TV0
  59.   double TV3;        // Dos time value for start of a time-out period
  60.   double Del0;       // Total time from TV0
  61.   double Del1;       // Delta time from last Diag call
  62.   double DosClockP;  // Previous value of the Dos clock for day cycle test
  63.   int DosDays;       // Number of days to add to Dos clock
  64.   int MuMaxW;        // Max number of characters to write on a line
  65.   int MuTot;         // Total number of characters on the line so far
  66.   VPtr huge ProtV;   // Pointer to protected Value being returned from +...
  67.   ofstream Disk;     // Text file, output
  68.   ofstream LogF;     // Text file, Log output file
  69.   struct date da;    // Defined in DOS.h, initialized in InitMulti
  70. // int  da_year;          // current year      use GetDateTime(); to fill this
  71. // char da_day;           // day of the month
  72. // char da_mon;           // month (1 = Jan) 
  73.   struct  time ti;
  74. // unsigned char ti_min;  // minutes           use GetDateTime(); to fill this
  75. // unsigned char ti_hour; // hours 
  76. // unsigned char ti_hund; // hundredths of seconds
  77. // unsigned char ti_sec;  // seconds
  78.  
  79. // ------- The following are set when this module is initialized
  80.   MultiSI MuMB(1); // Multi-precision modulo base, 0 => normal arith.
  81.  
  82. // ------- Implementation
  83.  
  84. // ------- Common hidden routines
  85.  
  86. // ------- |Y| = |Y| + |X|
  87. void IpAdd( MultiUI& X, MultiUI& Y, Mu1Digit& K)
  88. // Multi-precision integer add absolute values in place;  Y is changed
  89. // Y.N Must be >= X.N, X.S and Y.S not used or changed;  X not changed
  90. // Overflow super digit returned not zero if and only if Y overflows
  91. // MuErr flag not set.  Address of X and Y can be the same, then X is changed
  92. {
  93.   Mu2Digit T;
  94.   long i = 0;  K = 0;
  95.   while (i < X.N) {
  96.     T = X.V[i] + Y.V[i] + K; // Add next super digit with carry
  97.     if (T >= Base) {
  98.       K = 1;  Y.V[i] = T - Base;
  99.     } else {
  100.       K = 0;  Y.V[i] = T;
  101.     }
  102.     i++;
  103.   }
  104.   if (!K)  return;
  105.   while (i < Y.N) { // X = 0 from here on
  106.     if (Y.V[i] == MaxDigit) { // K = 1, carry to next super digit of Y
  107.       Y.V[i] = 0;
  108.     } else {
  109.       Y.V[i]++;  K = 0;  return; // Return K = 0}
  110.     }
  111.     i++;
  112.   }
  113.   Y.N++;
  114.   if (Y.N > Y.M) { // If overflow return K = 1
  115.     Y.N = Y.M;
  116.     Y.Norm();
  117.   } else {
  118.     Y.V[Y.N-1] = 1;  K = 0;  return; // Return K = 0
  119.   }
  120. } // --end-- IpAdd
  121.  
  122. // ------- |Y| = |Y| - |X|
  123. void IpSub( MultiUI& X, MultiUI& Y)
  124. // Multi-precision integer subtract absolute values in place;  Y is changed
  125. // |Y| Must be >= |X|, X.S and Y.S not used or changed;  X not changed
  126. // MuErr flag not set.  Address of X and Y can be the same, then X is changed
  127. {
  128.   Mu1Digit K = 0;
  129.   for (long i = 0; i < X.N; i++) {
  130.     Mu2Digit T = Y.V[i] - X.V[i] + K; // Subtract next 'digit' with borrow
  131.     if (T < 0) {
  132.       K = -1;  Y.V[i] = T + Base;
  133.     } else {
  134.       K = 0;  Y.V[i] = T;
  135.     }
  136.   }
  137.   if (!K || (X.N == Y.N)) { Y.Norm();  return; }
  138.   for ( ; i < Y.N; i++) { // X = 0 from here on
  139.     if (!Y.V[i]) { // K = -1, borrow from next super digit of Y
  140.       Y.V[i] = MaxDigit;
  141.     } else {
  142.       Y.V[i]--;  Y.Norm();  return;
  143.     }
  144.   }
  145. } // --end-- IpSub
  146.  
  147. // ------- X = |D| * X
  148. void IpMul1( Mu1Digit D, MultiUI& X, Mu1Digit& K)
  149. // Multi-precision one super digit multiply in place;  X is changed
  150. // K = Overflow super digit returned > zero if and only if X overflows
  151. // Signs not used
  152. {
  153.   D = fabs(D);  K = 0;
  154.   for (long i = 0; i < X.N; i++) {
  155.     Mu2Digit T = D * X.V[i] + K; // Multiply next super digit and add carry
  156.     K = floor(T / Base);
  157.     X.V[i] = T - K * Base;
  158.   }
  159.   if (!K)  return;
  160.   X.N++;
  161.   if (X.N > X.M) { // If overflow return K > 0
  162.     X.N = X.M;
  163.   } else {
  164.     X.V[X.N-1] = K;  K = 0;
  165.   }
  166. } // --end-- IpMul1
  167.  
  168. // ------- U = U / D
  169. void IpDiv1( MultiSI& U, Mu1Digit D, Mu1Digit& R)
  170. // Multi-precision one super digit divide in place, U is changed, R = Remainder
  171. // Allows literal D, MuErr set True if D = 0
  172. {
  173.   R = 0;
  174.   if (!D) {
  175.     MuWriteErr("Cannot divide by zero, continuing...");  return;
  176.   }
  177.   MuInterrupt();
  178.   if (MuAbort) {
  179.     U.Clear();  return;
  180.   }
  181.   Mu1Digit AD = fabs(D);
  182.   for (long i = U.N - 1; i >= 0; i--) {
  183.     Mu2Digit T = R * Base + U.V[i];//Divide next super digit and save remainder
  184.     U.V[i] = floor(T / AD);
  185.     R = T - U.V[i] * AD;
  186.   }
  187.   i = U.S;
  188.   if (U.S && R)  R = -R;
  189.   U.S = (U.S && !(D < 0)) || (!U.S && (D < 0)); // XOR
  190.   U.Norm();
  191. } // --end-- IpDiv1
  192.  
  193. // ------- Q = U / D, R = Rem, Slow Method (but fast for small numbers)
  194. void IpDivSlow( MultiSI& U, MultiSI& D, MultiSI& Q, MultiSI& R)
  195. // U and D are not changed, U is moved to R and then R is divided
  196. // in place to give Q and a remainder in R, it is OK for U and R
  197. // to have the same location in memory, but then U will be changed
  198. // Sets MuErr True if D = 0
  199. // See Knuth Vol. 2 of "The Art..." Algorithm D, pg. 237.
  200. {
  201.   Mu1Digit V1, V2, D1, K, QH;
  202.   Mu2Digit T;
  203.   long i, j, ij;
  204.   if (D.N == 1) { // Use IpDiv1 for a one super digit divide
  205.     Q.SetTo(U);  D1 = D.V[0];
  206.     if (D.S && D1)  D1 = -D1;
  207.     IpDiv1(Q, D1, K);
  208.     R.S = (K < 0);
  209.     R.V[0] = fabs(K);
  210.     R.N = 1;
  211.   } else {
  212.     R.SetTo(U); // SetTo is No-Op if same address
  213.     if (R.N < D.N) {
  214.       Q.Clear();  return;
  215.     }
  216.     Q.N = R.N - D.N + 1;
  217.     j = R.N;
  218.     R.V[R.N] = 0;
  219.     D.V[D.N] = 0;
  220.     V1 = D.V[D.N-1];
  221.     V2 = D.V[D.N-2];
  222.     D1 = floor( Base / (V1 + 1));    // D1. Normalize
  223.     if (D1 > 1) {
  224.       IpMul1( D1, D, K);  V1 = D.V[D.N-1];  V2 = D.V[D.N-2];
  225.       IpMul1( D1, R, K);
  226.       if (K)  R.V[j] = K;
  227.     }                               // D2. Init j done above
  228.     while (j >= D.N) {              // D3. Calculate Q hat
  229.       T = R.V[j] * Base + R.V[j-1];
  230.       if (V1 == R.V[j])
  231.     QH = MaxDigit;
  232.       else
  233.     QH = floor(T / V1);
  234.       while (V2 * QH > (T - QH * V1) * Base + R.V[j-2])  QH--;
  235. // QH =QH+1; .Diag for add back test
  236.       K = Base;
  237.       for (i = 0; i <= D.N; i++) {     // D4. Multiply and subtract
  238.     ij = i + j - D.N;
  239.     T = R.V[ij] - QH * D.V[i] + K + BSMB; // + BaseSq - Base
  240.     K = floor(T / Base);
  241.     R.V[ij] = T - K * Base;
  242.       }
  243.       Q.V[j - D.N] = QH;            // D5. Test remainder
  244.       if (K == MaxDigit) {
  245. // WriteLn("MuDiv: Doing an add back"); .Diag for add back test
  246.     Q.V[j - D.N] = QH - 1;    // D6. Add back
  247.     K = 0;  ij = j - D.N;
  248.     for (i = 0; i<= D.N; i++) {
  249.       T = D.V[i] + R.V[ij] + K;
  250.       K = floor(T / Base);
  251.       R.V[ij] = T - K * Base;
  252.       ij++;
  253.     }
  254.       }
  255.       j--;                    // D7. Loop on j
  256.       MuInterrupt();
  257.       if (MuAbort) {
  258.     Q.Clear();  R.Clear();  return;
  259.       }
  260.       if (KeyHit) {
  261.     cout << "Integer Divide: "
  262.          << floor( 100.0 * (R.N - j) / (R.N - D.N + 1))
  263.          << " Percent done" << nL;
  264.     KeyHit = False;
  265.       }
  266.     }
  267.     Q.S = (U.S && !D.S) || (!U.S && D.S); // XOR
  268.     R.S = U.S;
  269.     Q.Norm();
  270.     R.Norm();
  271.     if (D1 > 1) {       // D8. Unnormalize
  272.       IpDiv1(R, D1, K);
  273.       IpDiv1(D, D1, K);
  274.     }
  275.   }
  276. } // --end-- IpDivSlow
  277.  
  278. // ------- Q = U / D, R = Rem, Fast method for large numbers
  279. void IpDivFast( MultiSI& U, MultiSI& D, MultiSI& Q, MultiSI& R)
  280. // U and D are not changed, U is divided by D
  281. // to give Q and a remainder R, it is OK for U and R
  282. // to have the same location in memory, but then U will be changed
  283. // Sets MuErr True if D = 0
  284. {
  285.   MultiSI DL;  // Local Divisor scaled down (Points to D.V)
  286.   MultiSI M;   // 1 / D and 2*M
  287.   MultiSI MM;  // M * M
  288.   MultiSI MMD; // (M*M) * D
  289.   MultiSI UL;  // UL = Upper part of U (Points to U.V)
  290.   MultiSI QL;  // QL = U * M
  291.   MultiSI RL;  // Local remainder
  292.   MultiSI E;   // 1.0 for 1 / D and Error in Q
  293.   long i, j, pl, po, ps;
  294.  
  295.   if (D.N <= 2 || (U.N - D.N) <= 2) {
  296.     IpDivSlow(U, D, Q, R);  return;
  297.   }
  298.   pl = 5;
  299.   if (pl > (U.N - D.N))  pl = (U.N - D.N + 1);
  300.   j = (pl+1 > D.N) ? D.N : pl+1;
  301.   DL.N = DL.M = j;
  302.   DL.V = D.V + (D.N-j);
  303.   E.NMax( pl+1+DL.N);  E.N = E.M;
  304.   for (i = 0; i < E.N; i++)  E.V[i] = 0; // E = 1.0 Shifted
  305.   E.V[ E.N-1] = 1;
  306.   M.NMax( pl+12);
  307.   IpDivSlow(E, DL, M, E);
  308.   E.NMax(5);  DL.V = NULL;
  309.  
  310.   while (pl <= (U.N - D.N)) { // M = 2*M - D*M^2 = M + M - (M*M) * D
  311.     po = pl;  pl += pl;
  312.     if (pl > (U.N - D.N))  pl = (U.N - D.N) + 1;
  313.     MM.NMax( M.N + M.N);
  314.     MM.Mul(M, M);
  315.     ps = po+po-pl;
  316.     MM.V += ps;
  317.     MM.N -= ps;
  318.     j = (pl+1 > D.N) ? D.N : pl+1;
  319.     DL.N = DL.M = j;
  320.     DL.V = D.V + (D.N-j);
  321.     MMD.NMax( MM.N + DL.N);
  322.     MMD.Mul( MM, DL);
  323.     MMD.V += DL.N;
  324.     MMD.N -= DL.N;
  325.     MM.V -= ps;  MM.NMax(1);  DL.V = NULL;
  326.     M.RAdd(M);
  327.     for (j = M.N-1, i = j + pl-po, M.NMax(i+1), M.N = M.M;
  328.      i >= 0;  i--, j--) {
  329.       if (j >= 0)
  330.     M.V[i] = M.V[j];
  331.       else
  332.     M.V[i] = 0;
  333.     }
  334.     M.RSub( MMD);
  335.     MMD.V -= DL.N;  MMD.NMax(1);
  336.   }
  337.  
  338.   UL.N = UL.M = U.N - D.N + 1;
  339.   UL.V = U.V + (D.N-1);
  340.   QL.NMax( UL.N + M.N);
  341.   QL.Mul( UL, M);
  342.   UL.V = NULL;  M.NMax(1);
  343.   QL.N -= pl+1;
  344.   QL.V += pl+1;
  345.   RL.NMax( D.N + QL.N);
  346.   RL.Mul(D, QL);
  347.   RL.Sub(U, RL);
  348.   if (RL.Comp(D) >= 0) {  // if Rem > D
  349.     IpDivSlow( RL, D, E, RL);
  350.     QL.RAdd(E);
  351.   }
  352.   else if (RL.S) {  // if Rem < 0
  353.     RL.S = Plus;
  354.     IpDivSlow( RL, D, E, RL);
  355.     QL.RSub(E);
  356.     if (!RL.ZTest()) {  // if Rem != 0
  357.       RL.Sub(D, RL);
  358.       QL.RAdd1(-1);
  359.     }
  360.   }
  361.   else
  362.   ;
  363.   Q.SetTo( QL);
  364.   QL.V -= pl+1;
  365.   R.SetTo( RL);
  366. } // --end-- IpDivFast
  367.  
  368. // ------- Q = U / D, R = Rem
  369. void IpDiv( MultiSI& U, MultiSI& D, MultiSI& Q, MultiSI& R)
  370. // U and D are not changed, U is divided by D
  371. // to give Q and a remainder R, it is OK for U and R
  372. // to have the same location in memory, but then U will be changed
  373. // Sets MuErr True if D = 0
  374. {
  375.   float prod = (float) (U.N - D.N) * D.N;
  376.   if (prod / U.N < 344.0)
  377.     IpDivSlow(U, D, Q, R);
  378.   else
  379.     IpDivFast(U, D, Q, R);
  380. } // --end-- IpDiv
  381.  
  382. // --end-- Common hidden routines
  383.  
  384. // ------- MultiUI's method implementation
  385.  
  386. // ------- Constructor Multi-precision unsigned integer
  387. //           with just a max size
  388. MultiUI::MultiUI( long NMaxI)
  389. {
  390.   M = NMaxI;
  391.   if (M > MuNMax)  M = MuNMax;
  392.   long Size = sizeof( Mu1Digit);
  393.   Size = (M+1) * Size;
  394.   if ((V = (float huge*) farcalloc(M + 1, sizeof( Mu1Digit))) == NULL) {
  395.     MuWriteErr("Insufficient memory for Multi-precision number");
  396.     cout << "need " << Size << nL;
  397.     if (Echo)  LogF << "need " << Size << nL;
  398.     M = 1;
  399.     V = (float huge*) farcalloc(M + 1, sizeof( Mu1Digit));
  400.   }
  401.   Clear();
  402. } // --end-- MultiUI::MultuUI( long NMaxI)
  403.  
  404. // ------- NMax, change M = NMax
  405. void MultiUI::NMax( long NMaxI)
  406. {
  407.   if (NMaxI == M && V != NULL)  return;
  408.   if (NMaxI < 1) {
  409.     if (V != NULL) { farfree(V);  V = NULL; }
  410.     N = 0;  M = 0;  return;
  411.   }
  412.   if (NMaxI > MuNMax)  NMaxI = MuNMax;
  413.   VPtr v = (float huge*) farcalloc( NMaxI + 1, sizeof( Mu1Digit));
  414.   M = NMaxI;
  415.   if (V == NULL) {
  416.     V = v;  Clear();
  417.   } else {
  418.     if (N > NMaxI)  N = NMaxI;
  419.     for (long i = 0; i < N; i++)  v[i] = V[i];
  420.     farfree(V);
  421.     V = v;
  422.   }
  423.   v = NULL;
  424. } // --end-- NMax, change M = NMax
  425.  
  426. // ------- SetTo, this = X, copy used "digits" only
  427. void MultiUI::SetTo( MultiUI& X)
  428. {
  429.   if (V == X.V)  return;
  430.   if (V == NULL)  NMax(X.N); // Change size of this iff NULL
  431.   N = X.N;
  432.   if (N > M) {
  433.     N = M;
  434.     MuWriteErr("SetTo overflow, continuing...");
  435.   }
  436.   for (long i = 0; i < N; i++)  V[i] = X.V[i];
  437. } // --end-- MultiUI::SetTo, this = X
  438.  
  439. // ------- Normalize this
  440. void MultiUI::Norm()
  441. {
  442.   if (N < 1)  Clear();
  443.   for (long i = N - 1; !V[i] && i; i--)  ; // Delete leading zeros
  444.   N = i + 1;
  445. } // --end-- MultiUI::Norm()
  446.  
  447. // ------- AbComp = sign( |this| - |X|)
  448. int MultiUI::AbComp( MultiUI& X)
  449. // Si = -1 if |this| < |X|; Si = 0 if |this| = |X|; Si = +1 if |this| > |X|}
  450. // this.S and X.S not used or changed;  this, X not changed}
  451. {
  452.   if (N < X.N)  return -1;
  453.   if (N > X.N)  return +1;
  454.   for (long i = N - 1; (V[i] == X.V[i]) && i; i--)  ;
  455.   if (V[i] < X.V[i])  return -1;
  456.   if (V[i] > X.V[i])  return +1;
  457.   return 0;
  458. } // --end-- MultiUI::AbComp( MultiUI& X)
  459.  
  460. // ------- this = this + X
  461. void MultiUI::RAdd( MultiUI& X)
  462. // Sets MuErr True if overflow
  463. {
  464.   if (N < X.N) {  // If Digits in this < Digits in X
  465.     if (M >= X.N) {
  466.       for (long i = N; i < X.N; i++)  V[i] = 0;
  467.       N = X.N;
  468.     } else {
  469.       MuWriteErr("X too big to add, continuing...");
  470.     }
  471.   }
  472.   Mu1Digit K;
  473.   IpAdd(X, *this, K);
  474.   if (K > 0) MuWriteErr("Addition overflow, continuing...");
  475. } // --end-- MultiUI::RAdd( MultiUI& X)
  476.  
  477. // ------- this = this - X
  478. void MultiUI::RSub( MultiUI& X)
  479. // Sets MuErr True if N > this
  480. {
  481.   int i = AbComp(X);
  482.   if (!i)  Clear();
  483.   else if (i < 0)        // If this < X, Error
  484.     MuWriteErr("Unsigned subtraction error, continuing...");
  485.   else
  486.     IpSub(X, *this);
  487. } // --end-- MultiUI::RSub( MultiUI& X)
  488.  
  489. // ------- this = X + Y
  490. void MultiUI::Add( MultiUI& X, MultiUI& Y)
  491. // Sets MuErr True if overflow
  492. {
  493.   if (V == X.V)
  494.     RAdd(Y);
  495.   else if (V == Y.V)
  496.     RAdd(X);
  497.   else if (X.N >= Y.N) {
  498.     SetTo(X);  RAdd(Y);
  499.   } else {
  500.     SetTo(Y);  RAdd(X);
  501.   }
  502. } // --end-- MultiUI::Add( MultiUI& X, MultiUI& Y)
  503.  
  504. // ------- this = X - Y
  505. void MultiUI::Sub( MultiUI& X, MultiUI& Y)
  506. // Sets MuErr True if overflow
  507. {
  508.   MultiUI YL;
  509.   if (X.V == Y.V)  Clear();
  510.   else if (V == X.V)
  511.     RSub(Y);
  512.   else if (V == Y.V) {
  513.     MultiUI YL( Y.N);  YL.SetTo(Y);
  514.     SetTo(X);
  515.     RSub( YL);
  516.   } else {
  517.     SetTo(X);
  518.     RSub(Y);
  519.   }
  520. } // --end-- MultiUI::Sub( MultiUI& X, MultiUI& Y)
  521.  
  522. // ------- Boolean, True if this is Zero
  523. Bool MultiUI::ZTest()
  524. {
  525.   return (N == 1) && (V[0] == 0);
  526. } // --end-- MultiUI::ZTest()
  527.  
  528. // ------- Boolean, True if |this| = D1
  529. Bool MultiUI::EQ1( Mu1Digit D1)
  530. // this, D1 are not changed, allows literal D1
  531. {
  532.   return (N == 1) && (V[0] == D1);
  533. } // --end-- MultiUI::EQ1( Mu1Digit D1)
  534.  
  535. // ------- Boolean, True if |this| > D1
  536. Bool MultiUI::GT1( Mu1Digit D1)
  537. // this, D1 are not changed, allows literal D1
  538. {
  539.   return (N > 1) || (V[0] > D1);
  540. } // --end-- MultiUI::GT1( Mu1Digit D1)
  541.  
  542. // --end-- MultiUI's method implementation
  543.  
  544. // ------- MultiSI's method implementation
  545.  
  546. // ------- Change sign, this = - this
  547. void MultiSI::ChS() {
  548.   if (!ZTest())  S = !S;
  549. } // --end-- MultiSI::ChS()
  550.  
  551. // ------- this = X
  552. void MultiSI::SetTo( MultiSI& X) {
  553.   MultiUI::SetTo(X);  S = X.S;
  554. } // --end-- MultiSI::SetTo( MultiSI& X)
  555.  
  556. // ------- Normalize
  557. void MultiSI::Norm() {
  558.   MultiUI::Norm();
  559.   if (ZTest())  S = False; // Prevent -0
  560. } // --end-- MultiSI::Norm()
  561.  
  562. // ------- this = this + X
  563. void MultiSI::RAdd( MultiSI& X)
  564. // Sets MuErr True if overflow
  565. {
  566.   int i;
  567.   if (S == X.S)        // Same signs
  568.     MultiUI::RAdd(X);
  569.   else {        // Opposite signs
  570.     i = AbComp(X);
  571.     if (i < 0) {    // If |this| < |X|, |this| = |X| - |this|
  572.       MultiUI Temp(N);
  573.       Temp.SetTo( *this);// Temp = Small this
  574.       SetTo(X);        // this = Large X
  575.       IpSub( Temp, *this);
  576.     }
  577.     else if (i > 0)    // If |this| > |X|, |this| = |this| - |X|
  578.       IpSub(X, *this);
  579.     else
  580.       Clear();        // If |this| = |X|, this = 0
  581.   }
  582. } // --end-- MultiSI::RAdd( MultiSI& X)
  583.  
  584. // ------- this = this - X
  585. void MultiSI::RSub( MultiSI& X)
  586. // Sets MuErr True if overflow
  587. {
  588.   if (V == X.V)
  589.     Clear();
  590.   else {
  591.     X.S = !X.S;
  592.     RAdd(X);
  593.     X.S = !X.S;
  594.   }
  595. } // --end-- MultiSI::RSub( MultiSI& X)
  596.  
  597.  
  598. // ------- this = X + Y
  599. void MultiSI::Add( MultiSI& X, MultiSI& Y)
  600. // Sets MuErr True if overflow
  601. {
  602.   if (V == X.V)
  603.     RAdd(Y);
  604.   else if (V == Y.V)
  605.     RAdd(X);
  606.   else if (X.S == Y.S) {
  607.     MultiUI::Add(X, Y);  S = X.S;
  608.   } else {
  609.     int i = X.AbComp(Y);              // Signs are different
  610.     if (!i)  Clear();
  611.     else if (i > 0) {
  612.       SetTo(X);  IpSub(Y, *this);  // |X| > |Y|, so |X| - |Y|
  613.     } else {
  614.       SetTo(Y);  IpSub(X, *this);
  615.     }
  616.   }
  617. } // --end-- // MultiSI::Add( MultiSI& X, MultiSI& Y)
  618.  
  619.  
  620. // ------- this = X - Y
  621. void MultiSI::Sub( MultiSI& X, MultiSI& Y)
  622. // Sets MuErr True if overflow
  623. {
  624.   if (X.V == Y.V)  Clear();
  625.   else if (V == X.V)
  626.     RSub(Y);
  627.   else if (V == Y.V) {
  628.     RSub(X);  ChS();
  629.   } else {
  630.     Y.S = !Y.S;
  631.     Add(X, Y);
  632.     Y.S = !Y.S;
  633.   }
  634. } // --end-- MultiSI::Sub( MultiSI& X, MultiSI& Y)
  635.  
  636. // ------- Convert String to this
  637. void MultiSI::Value( char *St, int& i)
  638. // Returns i = # of character used
  639. // Allows St to be a literal, MuErr set True if overflow
  640. {
  641.   Mu1Digit K;
  642.   int Len;
  643.   int j, D;
  644.   Bool Fini; // Boolean
  645.   Bool OverFlow; // Boolean
  646.   for (i = 0; St[i] == ' '; i++) ;
  647.   if ((St[i] == '-') || (St[i] == '+'))  i++;
  648.   while ((St[i] != '\0') &&
  649.     (((St[i] >= '0') && (St[i] <= '9')) || (St[i] == ',')))
  650.     i++;
  651.   Len = i;
  652.   Clear();  Fini = False;  OverFlow = False;
  653.   if (!Len)  return;
  654.   for (j = 0; St[j] == ' '; j++);
  655.   if (St[j] == '-') { j++;  S = True; }
  656.   else if (St[j] == '+')  j++;
  657.   while (!Fini && (j < Len)) {
  658.     if ((St[j] >= '0') && (St[j] <= '9')) {
  659.       if ((N == M) && (V[N-1] >= Base / 10)) {
  660.     OverFlow = True;
  661.     Fini = True;
  662.       } else {
  663.     D = St[j] - '0';
  664.     IpMul1( 10, *this, K);
  665.     if (K > 0)  OverFlow = True;
  666.     V[0] += D;
  667.       }
  668.     }
  669.     else
  670.       if (St[j] != ',')  Fini = True;
  671.     j++;
  672.   }
  673.   if (OverFlow)  MuWriteErr("Input number overflow, continuing...");
  674.   Norm();
  675. } // --end-- MultiSI::Value()
  676.  
  677. // ------- this = D1 Mod Base
  678. void MultiSI::SetTo1( Mu1Digit D1)
  679. // Allows a literal D1, D1 an integer, |D1| < Base, D1 not changed
  680. {
  681.   Mu1Digit AbsD = fabs( D1);
  682.   N = 1;  S = (D1 < 0);
  683.   if (AbsD < Base)  V[0] = AbsD;
  684.   else
  685.     V[0] = AbsD - (int)(AbsD / Base) * Base;
  686. } // --end-- MultiSI::SetTo1()
  687.  
  688. // ------- this = Db Mod Base**4
  689. void MultiSI::SetToD( double Db)
  690. // Allows a literal Db, Db not changed, MuErr set True if overflow
  691. {
  692.   char St[255];
  693.   double AbsD;
  694.   int L, ML;
  695.   AbsD = fabs( Db);
  696.   sprintf( St, "%0.0f", AbsD);
  697.   L = strlen( St);  ML = 4 * MuDMax;
  698.   if (L > ML)
  699.     strcpy( St, &St[L - ML]);
  700.   Value( St, L);
  701.   if (Db < 0)  ChS(); // Prevents -0
  702. } // --end-- MultiSI::SetToD()
  703.  
  704. // ------- D1 = this Mod Base
  705. void MultiSI::Get1( Mu1Digit& D1)
  706. // this is not changed
  707. {
  708.   D1 = V[0];
  709.   if (S && D1)  D1 = -D1;
  710. } // --end--MultiSI::Get1()
  711.  
  712. // ------- Db = this Mod Base**4
  713. void MultiSI::GetD( double& Db)
  714. // this is not changed
  715. {
  716.   double T = Base;
  717.   Db = V[0];
  718.   for (long i = 1; (i < N) && (i < 4); i++) {
  719.     Db += V[i] * T; // Add next super digit
  720.     T *= Base;
  721.   }
  722.   if (S && Db)  Db = -Db;
  723. } // --end-- MultiSI::GetD()
  724.  
  725. // ------- this = this + D1
  726. void MultiSI::RAdd1( Mu1Digit D1)
  727. // Allows literal D1, D1 is not changed, sets MuErr True if overflow
  728. {
  729.   MultiSI DL(1);
  730.   DL.SetTo1( D1);
  731.   RAdd( DL);
  732. } // --end-- // MultiSI::RAdd1()
  733.  
  734. // ------- this = X + D1
  735. void MultiSI::Add1( MultiSI& X, Mu1Digit D1)
  736. // Allows literal D1, D1 is not changed, sets MuErr True if overflow
  737. {
  738.   SetTo(X);
  739.   RAdd1( D1);
  740. } // --end-- // MultiSI::Add1()
  741.  
  742. // ------- Comp = sign( this - X)
  743. int MultiSI::Comp( MultiSI& X)
  744. // Sign = -1 if this < X; Sign = 0 if this = X; Sign = +1 if this > X
  745. // this.S and X.S used but not changed;  this, X not changed
  746. {
  747.   if (!S && !X.S)  return AbComp(X);        // Both positive
  748.   else if (S && X.S)  return X.AbComp( *this);    // Both negative
  749.   else if (X.S)  return +1;            // this pos, X neg
  750.   else  return -1;                // this neg, X pos
  751. } // --end-- // MultiSI::Comp()
  752.  
  753. // ------- Output Character and a new line every MuMaxW,
  754. //         MuTot = characters on line so far
  755. void WriteMax( ostream& Out, char Ch)
  756. {
  757.   if ((&Out == &cout) || (MuMaxW <= 0))  Out << Ch;
  758.   else {
  759.     Out << Ch;
  760.     MuTot++;
  761.     if (MuTot >= MuMaxW) {
  762.       Out << nL;  MuTot = 0;
  763.     }
  764.   }
  765. } // --end-- // WritMaxC()
  766.  
  767. // ------- Output String and a new line every MuMaxW,
  768. //         MuTot = characters on line so far
  769. void WriteMax( ostream& Out, char *St)
  770. {
  771.   if ((&Out == &cout) || (MuMaxW <= 0))  Out << St;
  772.   else
  773.     for( int i = 0;  St[i] != '\0';  i++) {
  774.       Out << St[i];
  775.       MuTot++;
  776.       if (MuTot >= MuMaxW) {
  777.     Out << nL;  MuTot = 0;
  778.       }
  779.     }
  780. } // --end-- // WritMax()
  781.  
  782. // ------- Output String and line feed every MuMaxW, and a new line
  783. //         MuTot = characters on line so far
  784. void WriteMaxLn( ostream& Out, char *St)
  785. {
  786.   WriteMax( Out, St);  Out << nL;  MuTot = 0;
  787. } // --end-- // WritMaxLn()
  788.  
  789. // ------- Output this as a line of t   ext
  790. void MultiSI::Writ( ostream& Out)
  791. // this is not modified
  792. {
  793.   char  Sep = ',';
  794.  
  795.   if (MuDOnly)  Sep = ' ';
  796.   if (!M)  {WriteMax( Out, '0');  return;}
  797.   if (ShortN && N >= 3 && N > (ShortN / MuDMax))
  798.     { ShortWr( Out, ShortN);  return; }
  799.   char St[9];
  800.   long ToGo = (long)(N) * MuDMax;
  801.   if (S)  WriteMax( Out, '-');
  802.   sprintf( St, "%0.0f", Base + V[N - 1]);
  803.   for (int j = 1; (St[j] == '0') && (j != MuDMax); j++)  ;
  804.   WriteMax( Out, St[j]);
  805.   ToGo -= j;
  806.   long LenD = ToGo + 1;
  807.   for (j++; j <= MuDMax; j++) {
  808.     if (MuDpG && !(ToGo % MuDpG))  WriteMax( Out, Sep);
  809.     WriteMax( Out, St[j]);
  810.     ToGo--;
  811.   }
  812.   for (long i = 2; i <= N; i++) {
  813.     sprintf( St, "%0.0f", Base + V[N - i]);
  814.     for (j = 1; j <= MuDMax; j++) {
  815.       if (MuDpG && !(ToGo % MuDpG))  WriteMax( Out, Sep);
  816.       WriteMax( Out, St[j]);
  817.       ToGo--;
  818.     }
  819.   }
  820.   if (!MuDOnly) {
  821.     if (LenD >= MuLenD) {  //  Out << " (" << LenD << ')';
  822.       sprintf( St, "%ld", LenD);
  823.       if ( (&Out != &cout) && (MuMaxW > 0) &&
  824.         ((strlen( St) + MuTot + 3) > MuMaxW) ) {
  825.         Out << nL;  MuTot = 0;
  826.       }
  827.       if ((&Out == &cout) || (MuMaxW <= 0) || (MuTot != 0))
  828.         WriteMax( Out, ' ');
  829.       WriteMax( Out, '(');  WriteMax( Out, St);  WriteMax( Out, ')');
  830.     }
  831.   }
  832. } // --end-- // MultiSI::Writ()
  833.  
  834. // ------- Output this and a new line
  835. void MultiSI::WritLn( ostream& Out)
  836. {
  837.   Writ( Out);  Out << nL;  MuTot = 0;
  838. } // --end-- // MultiSI::WritLn()
  839.  
  840. // ------- Output this in short form ... if more than Short digits
  841. void MultiSI::ShortWr( ostream& Out, long Short)
  842. // this is not modified
  843. {
  844.   if (!M)  {Out << '0';  return;}
  845.   char St[9];
  846.   if ((N < 3) || (N <= (Short / MuDMax))) {
  847.     Writ( Out);  return;
  848.   }
  849.   long ToGo = (long)(N) * MuDMax;
  850.   if (S)  Out << '-';
  851.   sprintf( St, "%0.0f", Base + V[N - 1]);
  852.   for (int j = 1; (St[j] == '0') && (j != MuDMax); j++)  ;
  853.   Out << St[j];  int Did = 1;
  854.   ToGo -= j;
  855.   long LenD = ToGo + 1;
  856.   for (j++; (j <= MuDMax) && (Did < 5); j++) {
  857.     Out << St[j];
  858.     Did++;
  859.   }
  860.   sprintf( St, "%0.0f", Base + V[N - 2]);
  861.   for (j = 1; j < 6-Did; j++) {
  862.     Out << St[j];
  863.   }
  864.   Out << ",...,";
  865.   sprintf( St, "%0.0f", Base + V[0]);
  866.   for (j = MuDMax-4; j < MuDMax+1; j++) {
  867.     Out << St[j];
  868.   }
  869.   Out << " (" << LenD << ')';
  870. } // --end-- // MultiSI::ShortWr()
  871.  
  872. // ------- Output this short and a new line
  873. void MultiSI::ShortWrLn( ostream& Out, long Short)
  874. {
  875.   ShortWr( Out, Short);  Out << nL;
  876. } // --end-- // MultiSI::ShortWrLn()
  877.  
  878. // ------- this = this * D1
  879. void MultiSI::RMul1( Mu1Digit D1)
  880. // Multi-precision one super digit multiply; D1 is not changed
  881. // MuErr set true if this overflows
  882. {
  883.   Mu1Digit K;
  884.   S = (S && !(D1 < 0)) || (!S && (D1 < 0)); // XOR
  885.   IpMul1( D1, *this, K);
  886.   if (K > 0)
  887.     MuWriteErr("One digit multiply overflow, continuing...");
  888. } // --end-- // MultiSI::RMul1()
  889.  
  890. // ------- this = X * D1
  891. void MultiSI::Mul1( MultiSI& X, Mu1Digit D1)
  892. // Multi-precision one super digit multiply; X and D1 are not changed
  893. // MuErr set true if this overflows
  894. {
  895.   SetTo(X);  RMul1( D1);
  896. } // --end-- // MultiSI::Mul1()
  897.  
  898. // ------- this = X * Y
  899. void MultiSI::Mul( MultiSI& X, MultiSI& Y)
  900. // X or Y or both may have the same address in memory as this
  901. // X, Y are not changed unless they share memory with this
  902. // Sets MuErr True if overflow
  903. {
  904.   float prod = (float) X.N * Y.N;
  905.   if (prod < 40.0)
  906.     MulSlow(X, Y);
  907.   else if (prod / (X.N + Y.N) < 344.0)  // 4816 * 4816 dec digs
  908.     MulCon(X, Y);
  909.   else
  910.     MulTran(X, Y);
  911. } // --end-- // MultiSI::Mul()
  912.  
  913. // ------- this = X * Y, Slow Method (but fast for small numbers)
  914. void MultiSI::MulSlow( MultiSI& X, MultiSI& Y)
  915. // X or Y or both may have the same address in memory as this
  916. // X, Y are not changed unless they share memory with this
  917. // Sets MuErr True if overflow
  918. {
  919.   long i, j, ij;
  920.   Mu1Digit K;
  921.   Mu2Digit T;
  922.   VPtr XVP, YVP, VP;
  923.   MultiSI XL = X;
  924.   MultiSI YL = Y;
  925.   MultiSI TL = XL; // Temp pointer for swap
  926.   if (X.V == V) {
  927.     XL.V = NULL;  XL.NMax(X.N); // Change M = NMax
  928.     XL.SetTo(X);
  929.   }
  930.   else if (Y.V == V) {
  931.     YL.V = NULL;  YL.NMax(Y.N); // Change M = NMax
  932.     YL.SetTo(Y);
  933.   }
  934.   if (X.V == Y.V)  YL = XL;
  935.   else if (XL.N < YL.N) { TL = XL;  XL = YL;  YL = TL; }
  936.   S = (XL.S && !YL.S) || (!XL.S && YL.S); // XOR
  937.   ij = (XL.N < M) ? XL.N : M;
  938.   for (i = 0, VP = V;  i < ij;  i++, VP++)  *VP = 0; // Clear lower of this
  939.   KeyHit = False;
  940.   for (j = 0, YVP = YL.V;  j < YL.N;  j++, YVP++) {
  941.     for (K = 0, i = 0, ij = j, VP = V + j, XVP = XL.V;
  942.     i < XL.N;  i++, ij++, VP++, XVP++) {
  943.       if (ij < M) {        // Mult, add and carry next Digit
  944.     T = (double) *XVP * *YVP + *VP + K;
  945.     K = floor(T / Base);
  946.     *VP = T - K * Base;
  947.       }
  948.       else
  949.     i = XL.N; // Break out of inner loop
  950.     }
  951.     if (ij < M)  V[ij] = K;
  952.     MuInterrupt();
  953.     if (MuAbort) {
  954.       Clear();  TL.V = NULL;
  955.       if ((XL.V == X.V) || (XL.V == Y.V))  XL.V = NULL;
  956.       if ((YL.V == X.V) || (YL.V == Y.V) || (YL.V == XL.V))  YL.V = NULL;
  957.       return;
  958.     }
  959.     if (KeyHit) {
  960.       cout << "Integer Multiply (Slow): "
  961.        << floor( 100.0 * (j+1) / YL.N) << " Percent done" << nL;
  962.       KeyHit = False;
  963.     }
  964.   }
  965.   if (K)  ij++;
  966.   if (ij > M) {
  967.     ij = M;  MuWriteErr("MulSlow: Multiplication overflow, continuing...");
  968.   }
  969.   N = ij;
  970.   Norm();  TL.V = NULL;
  971.   if ((XL.V == X.V) || (XL.V == Y.V))  XL.V = NULL;
  972.   if ((YL.V == X.V) || (YL.V == Y.V) || (YL.V == XL.V))  YL.V = NULL;
  973. } // --end-- // MultiSI::MulSlow()
  974.  
  975. // ------- this = X * Y, Convolution method
  976. void MultiSI::MulCon( MultiSI& X, MultiSI& Y)
  977. // X or Y or both may have the same address in memory as this
  978. // X, Y are not changed unless they share memory with this
  979. // Sets MuErr True if overflow
  980. {
  981.   long i, j, size;
  982.   long double K;
  983.   long double T;
  984.   MultiSI XL;
  985.   MultiSI YL;
  986.   VPtr XVP, YVP, VP;
  987.   bytes16 huge *b16A;  // bytes16 array
  988.   bytes16 huge *b16P;  // bytes16 pointer
  989.   size = X.N + Y.N - 1;
  990.   if ( (b16A = (bytes16 huge*) farcalloc( size, sizeof( bytes16))) == NULL) {
  991.     MuWriteErr(
  992.       "Integer Multiplication (Con.) not enough memory, continuing...");
  993.     Clear();  return;
  994.   }
  995.   if (Y.N < X.N)  { XL = X;  YL = Y; }
  996.         else  { XL = Y;  YL = X; }
  997.   S = (XL.S && !YL.S) || (!XL.S && YL.S); // XOR
  998.   for (i = 0, b16P = b16A;  i < size;  i++, b16P++)
  999.     b16P->v = 0; // Clear convolution
  1000.   KeyHit = False;
  1001.   for (j = 0, YVP = YL.V;  j < YL.N;  j++, YVP++) {
  1002.     for (i = 0, b16P = b16A + j, XVP = XL.V;  i < XL.N;  i++, b16P++, XVP++)
  1003.       b16P->v += (long double) *XVP * *YVP;
  1004.     if (!((j+1) % 184467L)) {  // prevent overflow of long double value
  1005.       for (K = 0, i = 0, b16P = b16A;  i < size;  i++, b16P++) {
  1006.     T = b16P->v + K;    // carry next Digit
  1007.     K = floorl(T / Base);
  1008.     b16P->v = T - K * Base;
  1009.       }
  1010.     }
  1011.     MuInterrupt();
  1012.     if (MuAbort) {
  1013.       XL.V = NULL;  YL.V = NULL;
  1014.       farfree( b16A);  Clear();  return;
  1015.     }
  1016.     if (KeyHit) {
  1017.       cout << "Integer Multiply (Con.): "
  1018.        << floor( 100.0 * (j+1) / YL.N) << " Percent done" << nL;
  1019.       KeyHit = False;
  1020.     }
  1021.   }
  1022.   for (K = 0, i = 0, b16P = b16A, VP = V;  i < size;  i++, b16P++, VP++) {
  1023.     if (i < M) {       // carry next Digit
  1024.       T = b16P->v + K;
  1025.       K = floorl(T / Base);
  1026.       *VP = T - K * Base;
  1027.     }
  1028.     else
  1029.       i = size; // Break out of loop
  1030.   }
  1031.   if (i < M)  V[i] = K;
  1032.   if (K)  i++;
  1033.   if (i > M) {
  1034.     i = M;  MuWriteErr("MulCon: Multiplication overflow, continuing...");
  1035.   }
  1036.   N = i;
  1037.   XL.V = NULL;  YL.V = NULL;
  1038.   farfree( b16A);  Norm();
  1039. } // --end-- // MultiSI::MulCon()
  1040.  
  1041. // ------- Generate data for FFT
  1042. void FftGenDat( MultiSI& X, bytes8 huge *data, long n, int DDSD)
  1043. {
  1044.   long i, j, ii;
  1045.   long double K;
  1046.   long double T;
  1047.   long double Base2;
  1048.   long double Ten2;
  1049.   int d, left;
  1050.  
  1051.   for (Base2 = 10.0, i = 1;  i < DDSD; i++)  Base2 *= 10.0; // 10^DDSD
  1052.   for (j = 1; j <= n; j++)  data[j].v = 0.0;
  1053.   j = 1;  d = DDSD;  left = 7;  K = 0;
  1054.   for (i = 0; i < X.N; i++) {
  1055.     for (Ten2 = 1.0, ii = 0;  ii < DDSD-d; ii++)  Ten2 *= 10.0; // 10^(DDSD-d)
  1056.     T = X.V[i] * Ten2;  left = 7 + (DDSD-d);  d = DDSD;
  1057.     while (left > 0) {
  1058.       T += K;
  1059.       K = floorl(T / Base2);
  1060.       data[j].v += T - K * Base2;
  1061.       T = 0;
  1062.       if (d == DDSD)  j++;
  1063.       left -= d;
  1064.       if (!left && d != DDSD)  d = DDSD-d;
  1065.       if (left && left < d)  d = left;
  1066.  
  1067.       if (!(i % 1000)) {
  1068.     if (kbhit()) {
  1069.       MuInterrupt();  KeyHit = False;
  1070.       if (MuAbort)  return;
  1071.       cout << "FftGenDat: Generating data, i = " << i <<" of "<< n <<nL;
  1072.     }
  1073.       }
  1074.     }
  1075.   }
  1076. } // --end-- // FftGenDat
  1077.  
  1078. // ------- Store data from FFT
  1079. void FftStoDat( MultiSI& X, bytes8 huge *data, long n, int DDSD)
  1080. {
  1081.   long i, j, ii, size;
  1082.   long double K;
  1083.   long double T;
  1084.   long double Base2;
  1085.   long double Ten2;
  1086.   int d, left, over;
  1087.  
  1088.   for (Base2 = 10.0, i = 1;  i < DDSD; i++)  Base2 *= 10.0; // 10^DDSD
  1089.   for (size = n;  size >= 1 && data[size].v < 0.5 ;  size--) ;
  1090.   for (K = 0, j = 1;  j <= size;  j++) {
  1091.     T = floorl( data[j].v + 0.5) + K;        // carry next Digit
  1092.     K = floorl(T / Base2);
  1093.     data[j].v = T - K * Base2;
  1094.     if (j == size && K != 0.0) { size++;  data[size].v = 0.0; }
  1095.   }
  1096.   X.N = (size * DDSD + 6) / 7;
  1097.   over = (X.N > X.M+1);
  1098.   if (X.N > X.M)    X.N = X.M;
  1099.   for (i = 0; i < X.N; i++)  X.V[i] = 0;
  1100.   X.V[X.M] = 0;
  1101.  
  1102.   j = 1;  d = 0;  K = 0;
  1103.   for (i = 0; i < X.N; i++) {
  1104.     for (Ten2 = 1.0, ii = 0;  ii < d; ii++)  Ten2 *= 10.0; // 10^d
  1105.     left = 7;  d += DDSD;
  1106.     while (left > 0) {
  1107.       if (j > size)  T = K;
  1108.       else
  1109.     T = data[j].v * Ten2 + K;
  1110.       K = floorl(T / Base);
  1111.       X.V[i] += T - K * Base;
  1112.       Ten2 *= Base2;
  1113.       j++;
  1114.       left -= d;
  1115.       if (left <= 0)  d = -left;  else  d = DDSD;
  1116.  
  1117.       if (!(i % 1000)) {
  1118.     if (kbhit()) {
  1119.       MuInterrupt();  KeyHit = False;
  1120.       if (MuAbort)  return;
  1121.       cout << "FftGenDat: Generating data, i = " << i <<" of "<< n <<nL;
  1122.     }
  1123.       }
  1124.     }
  1125.   }
  1126.   if (K != 0.0)  over = True;
  1127.   if (over)  MuWriteErr("FftStoDat: Multiplication overflow, continuing...");
  1128.   X.Norm();
  1129. } // --end-- // FftStoDat
  1130.  
  1131. // ------- this = X * Y, Transform method  // Not done yet !!!
  1132. void MultiSI::MulTran( MultiSI& X, MultiSI& Y)
  1133. // X or Y or both may have the same address in memory as this
  1134. // X, Y are not changed unless they share memory with this
  1135. // Sets MuErr True if overflow
  1136. {
  1137.   bytes8 huge *data;    long n;
  1138.   bytes8 huge *respns;  long m;
  1139.   Bool isign;           bytes8 huge *ans;  // All vectors [1.. ]
  1140.   bytes8 huge *fft;
  1141.  
  1142.   long n0;
  1143.   int DDSD;     // Decimal digits per super digit in FFT
  1144.  
  1145. // Results of tests:  (n = super digits in FFT, L + M - 1, 99..99 * 99..99)
  1146. // Using double data type to store FFT
  1147. // -Super digit-  --n--  -MaxErr-    --n--  -MaxErr-
  1148. //    9999999      2^4     0.031      2^5     0.125
  1149. //     999999      2^9     0.063      2^10    0.156
  1150. //      99999      2^15    0.063      2^16    0.141
  1151. //       9999      2^20    0.06 est   2^15    0.16 est
  1152. //        999      2^25    0.06 est   2^16    0.16 est
  1153.  
  1154.   DDSD = 7;
  1155.   n0 = X.N + Y.N - 1;
  1156.   if (n0 <= 16) ;  // 2^4
  1157.   else {
  1158.     DDSD = 6;
  1159.     n0 = (7 * X.N + 5) / 6 + (7 * Y.N + 5) / 6 - 1;
  1160.     if (n0 <= 512) ;  // 2^9
  1161.   else {
  1162.     DDSD = 5;
  1163.     n0 = (7 * X.N + 4) / 5 + (7 * Y.N + 4) / 5 - 1;
  1164.     if (n0 <= 32768L) ;  // 2^15
  1165.   else {
  1166.     DDSD = 4;
  1167.     n0 = (7 * X.N + 3) / 4 + (7 * Y.N + 3) / 4 - 1;
  1168.     if (n0 <= 1048576L) ;  // 2^20
  1169.   else {
  1170.     DDSD = 3;
  1171.     n0 = (7 * X.N + 2) / 3 + (7 * Y.N + 2) / 3 - 1;
  1172.     if (n0 <= 33554432L) ;  // 2^25
  1173.   else {
  1174.     DDSD = 2;
  1175.     n0 = (7 * X.N + 1) / 2 + (7 * Y.N + 1) / 2 - 1;
  1176.   } } } } }
  1177.  
  1178.   for (n = 2;  n < n0;  n *= 2) ;  // n = 2 ^ p >= n0  (n >= 2 also)
  1179. //if (n > 16000)
  1180. //  cout << "MulTran: l, m, DDSD, n = " << X.N << ", " << Y.N << ", "
  1181. //     << DDSD << ", " << n << nL;
  1182.   m = 0;  isign = 1;
  1183.   ans = vector8(1, 2 * n);
  1184.   fft = vector8(1, 2 * n);
  1185.   if (ans == NULL)  MuWriteErr(
  1186.     "Integer Multiplication (Tran.) not enough memory, continuing...");
  1187.   if (fft == NULL) {
  1188.     MuWriteErr(
  1189.     "Integer Multiplication (Tran.) not enough memory, continuing...");
  1190.     cout << "MulTran: l, m, DDSD, n = " << X.N << ", " << Y.N << ", "
  1191.          << DDSD << ", " << n << nL;
  1192.   }
  1193.   data   = ans;
  1194.   respns = ans + n;
  1195.   if (!MuAbort && !MuErr)  FftGenDat(X, data, n, DDSD);
  1196.   if (!MuAbort && !MuErr)  FftGenDat(Y, respns, n, DDSD);
  1197.   if (!MuAbort && !MuErr)  convlv( data, n, respns, m, isign, ans, fft);
  1198.   if (!MuAbort && !MuErr)  FftStoDat( *this, ans, n, DDSD);
  1199.   free_vector8( fft, 1, 2 * n);
  1200.   free_vector8( ans, 1, 2 * n);
  1201.   if (MuAbort || MuErr)  Clear();
  1202.   Norm();
  1203. }  // --end-- // MultiSI::MulTran()
  1204.  
  1205. // ------- this = this * X
  1206. void MultiSI::RMul( MultiSI& X)
  1207. // X may have the same address in memory as this
  1208. // X is not changed unless it shares memory with this
  1209. // Sets MuErr True if overflow
  1210. {
  1211.   Mul( *this, X);
  1212. } // --end-- // MultiSI::RMul()
  1213.  
  1214. // ------- this = X * X
  1215. void MultiSI::Sq( MultiSI& X)
  1216. // X may have the same address in memory as this
  1217. // X is not changed unless it shares memory with this
  1218. // Sets MuErr True if overflow
  1219. {
  1220.   Mul(X, X);
  1221. } // --end-- // MultiSI::Sq()
  1222.  
  1223. // ------- this = this * this
  1224. void MultiSI::RSq()
  1225. // Sets MuErr True if overflow
  1226. {
  1227.   Mul( *this, *this);
  1228. } // --end-- // MultiSI::RSq()
  1229.  
  1230. // ------- this = this Mod MuMB
  1231. void MultiSI::ModMB()
  1232. // this is changed
  1233. {
  1234.   if (MuMB.ZTest())  return;
  1235.   int i = AbComp( MuMB);
  1236.   if (i >= 0) { // if |this| >= |MuMB|
  1237.     MultiSI QL(N);
  1238.     IpDiv( *this, MuMB, QL, *this);
  1239.   }
  1240. } // --end-- // MultiSI::ModMB()
  1241.  
  1242. // ------- this = this / D1
  1243. void MultiSI::RDiv1( Mu1Digit D1)
  1244. // Multi-precision one super digit divide, D1 is not changed
  1245. // Allows literal D1, MuErr set True if D1 = 0
  1246. {
  1247.   Mu1Digit RL;
  1248.   IpDiv1( *this, D1, RL);
  1249. } // --end-- // MultiSI::RDiv1()
  1250.  
  1251. // ------- this = U / D1
  1252. void MultiSI::Div1( MultiSI& U, Mu1Digit D1)
  1253. // Multi-precision one super digit divide, D1 and U not changed
  1254. // U and this may have same address in memory, then U is changed
  1255. // Allows literal D1, MuErr set True if D1 = 0
  1256. {
  1257.   Mu1Digit RL;
  1258.   SetTo(U);
  1259.   IpDiv1( *this, D1, RL);
  1260. } // --end-- // MultiSI::Div1()
  1261.  
  1262. // ------- R1 = Rem( this / D1)
  1263. void MultiSI::Mod1( Mu1Digit D1, Mu1Digit& R1)
  1264. // Multi-precision one super digit Modulo, D1 and this not changed
  1265. // D1 and R1 may have same address in memory, then D1 is changed
  1266. // Allows literal D1, MuErr set True if D1 = 0
  1267. {
  1268.   MultiSI QL(N);
  1269.   QL.SetTo( *this);
  1270.   IpDiv1( QL, D1, R1);
  1271. } // --end-- // MultiSI::Mod1()
  1272.  
  1273. // ------- this = this / D1, R1 = Rem
  1274. void MultiSI::RDiv1QR( Mu1Digit D1, Mu1Digit& R1)
  1275. // Multi-precision one super digit Divide Q & R.  D1 and U not changed
  1276. // D1 and R1 may have same address in memory, then D1 is changed
  1277. // Allows literal D1, MuErr set True if D1 = 0
  1278. {
  1279.   IpDiv1( *this, D1, R1);
  1280. } // --end-- // MultiSI::RDiv1QR()
  1281.  
  1282. // ------- this = U / D1, R1 = Rem
  1283. void MultiSI::Div1QR( MultiSI& U, Mu1Digit D1, Mu1Digit& R1)
  1284. // Multi-precision one super digit Divide Q & R.  D1 and U not changed
  1285. // D1 and R1 may have same address in memory, then D1 is changed
  1286. // Allows literal D1, MuErr set True if D1 = 0
  1287. {
  1288.   SetTo(U);
  1289.   IpDiv1( *this, D1, R1);
  1290. } // --end-- // MultiSI::Div1QR()
  1291.  
  1292. // ------- this = U / D
  1293. void MultiSI::Divi( MultiSI& U, MultiSI& D)
  1294. // U or D or both may have the same address in memory as this
  1295. // U, D are not changed unless they share memory with this
  1296. // Sets MuErr True if D = 0
  1297. {
  1298.   MultiSI DL = D;
  1299.   if (D.V == V) {
  1300.     DL.V = NULL;  DL.NMax(D.N); // Change M = NMax
  1301.     DL.SetTo(D);
  1302.   }
  1303.   MultiSI RL(U.N);  RL.SetTo(U);
  1304.   IpDiv( RL, DL, *this, RL);
  1305.   if (DL.V == D.V)  DL.V = NULL;
  1306. } // --end-- // MultiSI::Divi()
  1307.  
  1308. // ------- this = U / D, Slow Method (but fast for small numbers)
  1309. void MultiSI::DivSlow( MultiSI& U, MultiSI& D)
  1310. // U or D or both may have the same address in memory as this
  1311. // U, D are not changed unless they share memory with this
  1312. // Sets MuErr True if D = 0
  1313. {
  1314.   MultiSI DL = D;
  1315.   if (D.V == V) {
  1316.     DL.V = NULL;  DL.NMax(D.N); // Change M = NMax
  1317.     DL.SetTo(D);
  1318.   }
  1319.   MultiSI RL(U.N);  RL.SetTo(U);
  1320.   IpDivSlow( RL, DL, *this, RL);
  1321.   if (DL.V == D.V)  DL.V = NULL;
  1322. } // --end-- // MultiSI::DivSlow()
  1323.  
  1324. // ------- this = U / D, Fast method for large numbers
  1325. void MultiSI::DivFast( MultiSI& U, MultiSI& D)
  1326. // U or D or both may have the same address in memory as this
  1327. // U, D are not changed unless they share memory with this
  1328. // Sets MuErr True if D = 0
  1329. {
  1330.   MultiSI DL = D;
  1331.   if (D.V == V) {
  1332.     DL.V = NULL;  DL.NMax(D.N); // Change M = NMax
  1333.     DL.SetTo(D);
  1334.   }
  1335.   MultiSI RL(U.N);  RL.SetTo(U);
  1336.   IpDivFast( RL, DL, *this, RL);
  1337.   if (DL.V == D.V)  DL.V = NULL;
  1338. } // --end-- // MultiSI::DivFast()
  1339.  
  1340. // ------- this = this / D
  1341. void MultiSI::RDiv( MultiSI& D)
  1342. // D may have the same address in memory as this
  1343. // D is not changed unless it shares memory with this
  1344. // Sets MuErr True if D = 0
  1345. {
  1346.   Divi( *this, D);
  1347. } // --end-- // MultiSI::RDiv()
  1348.  
  1349. // ------- this = Rem(U / D)
  1350. void MultiSI::Modu( MultiSI& U, MultiSI& D)
  1351. // U or D or both may have the same address in memory as this
  1352. // U, D are not changed unless they share memory with this
  1353. // Sets MuErr True if D = 0
  1354. {
  1355.   MultiSI DL = D;
  1356.   if (D.V == V) {
  1357.     DL.V = NULL;  DL.NMax(D.N); // Change M = NMax
  1358.     DL.SetTo(D);
  1359.   }
  1360.   MultiSI QL(U.N);
  1361.   SetTo(U);
  1362.   IpDiv( *this, DL, QL, *this);
  1363.   if (DL.V == D.V)  DL.V = NULL;
  1364. } // --end-- // MultiSI::Modu()
  1365.  
  1366. // ------- this = Rem( this / D)
  1367. void MultiSI::RMod( MultiSI& D)
  1368. // D may have the same address in memory as this
  1369. // D is not changed unless it shares memory with this
  1370. // Sets MuErr True if D = 0
  1371. {
  1372.   Modu( *this, D);
  1373. } // --end-- // MultiSI::RMod()
  1374.  
  1375. // ------- this = U / D, R = Rem
  1376. void MultiSI::DivQR( MultiSI& U, MultiSI& D, MultiSI& R)
  1377. // U or D or both may have the same address in memory as this or R
  1378. // U, D are not changed unless they share memory with this or R
  1379. // this and R may not have the same location in memory. Sets MuErr True if D = 0
  1380. {
  1381.   if (V == R.V) {
  1382.     MuWriteErr(
  1383.      "Cannot set same location to both quotient and remainder, continuing...");
  1384.     return;
  1385.   }
  1386.   MultiSI DL = D;
  1387.   if ((D.V == V) || (D.V == R.V)) {
  1388.     DL.V = NULL;  DL.NMax(D.N); // Change M = NMax
  1389.     DL.SetTo(D);
  1390.   }
  1391.   R.SetTo(U);
  1392.   IpDiv(R, DL, *this, R);
  1393.   if (DL.V == D.V)  DL.V = NULL;
  1394. } // --end-- // MultiSI::DivQR()
  1395.  
  1396. // ------- this = U / D, R = Rem, Slow Method (but fast for small numbers)
  1397. void MultiSI::DivQRSlow( MultiSI& U, MultiSI& D, MultiSI& R)
  1398. // U or D or both may have the same address in memory as this or R
  1399. // U, D are not changed unless they share memory with this or R
  1400. // this and R may not have the same location in memory. Sets MuErr True if D=0
  1401. {
  1402.   if (V == R.V) {
  1403.     MuWriteErr(
  1404.      "Cannot set same location to both quotient and remainder, continuing...");
  1405.     return;
  1406.   }
  1407.   MultiSI DL = D;
  1408.   if ((D.V == V) || (D.V == R.V)) {
  1409.     DL.V = NULL;  DL.NMax(D.N); // Change M = NMax
  1410.     DL.SetTo(D);
  1411.   }
  1412.   R.SetTo(U);
  1413.   IpDivSlow(R, DL, *this, R);
  1414.   if (DL.V == D.V)  DL.V = NULL;
  1415. } // --end-- // MultiSI::DivQRSlow()
  1416.  
  1417. // ------- this = U / D, R = Rem, Fast method for large numbers
  1418. void MultiSI::DivQRFast( MultiSI& U, MultiSI& D, MultiSI& R)
  1419. // U or D or both may have the same address in memory as this or R
  1420. // U, D are not changed unless they share memory with this or R
  1421. // this and R may not have the same location in memory. Sets MuErr True if D=0
  1422. {
  1423.   if (V == R.V) {
  1424.     MuWriteErr(
  1425.      "Cannot set same location to both quotient and remainder, continuing...");
  1426.     return;
  1427.   }
  1428.   MultiSI DL = D;
  1429.   if ((D.V == V) || (D.V == R.V)) {
  1430.     DL.V = NULL;  DL.NMax(D.N); // Change M = NMax
  1431.     DL.SetTo(D);
  1432.   }
  1433.   R.SetTo(U);
  1434.   IpDivFast(R, DL, *this, R);
  1435.   if (DL.V == D.V)  DL.V = NULL;
  1436. } // --end-- // MultiSI::DivQRFast()
  1437.  
  1438. // ------- this = this / D, R = Rem
  1439. void MultiSI::RDivQR( MultiSI& D, MultiSI& R)
  1440. // this may have the same address in memory as D or R
  1441. // D is not changed unless it shares memory with this or R
  1442. // Sets MuErr True if D = 0
  1443. {
  1444.   DivQR( *this, D, R);
  1445. } // --end-- // MultiSI::RDivQR()
  1446.  
  1447. // ------- this = (B ** P) Mod MuMB
  1448. void MultiSI::PowMB( MultiSI& B, MultiSI& P)
  1449. // B or P or both may have the same address in memory as this
  1450. // B, P are not changed unless they share memory with this
  1451. // Sets MuErr True if overflow or error
  1452. {
  1453.   long L;
  1454.   Mu1Digit R;
  1455.   if (B.ZTest()) { // B = 0
  1456.     if (P.S)
  1457.       MuWriteErr("Cannot raise zero to a negative power");
  1458.     else if (P.ZTest()) // P = 0
  1459.       MuWriteErr("Cannot raise zero to the zero power");
  1460.     Clear();  return;
  1461.   }
  1462.   if ((P.S) && ((B.N > 1) || (B.V[0] > 1))) { // (>1) ** -P
  1463.     Clear();  return;
  1464.   }
  1465.   if ((B.N == 1) && (B.V[0] == 1)) { // B = +/-1
  1466.     L = floor(P.V[0]);
  1467.     S = B.S && (L % 2);
  1468.     N = 1;  V[0] = 1;  return;
  1469.   }
  1470.   MultiSI BL(M);    BL.SetTo(B);
  1471.   MultiSI PL(P.N);  PL.SetTo(P);
  1472.   SetTo1(1);
  1473.   Bool Fini = False;
  1474.   while (!Fini) {
  1475.     L = floor( PL.V[0]);
  1476.     if (L % 2) {
  1477.       Mul( BL, *this);  ModMB();
  1478.     }
  1479.     IpDiv1( PL, 2, R);
  1480.     if (PL.ZTest())  Fini = True;
  1481.     else {
  1482.       BL.Mul( BL, BL);  BL.ModMB();
  1483.     }
  1484.     if (MuAbort) {
  1485.       Clear();  Fini = True;
  1486.     }
  1487.   }
  1488. } // --end-- // MultiSI::PowMB()
  1489.  
  1490. // ------- this = (this ** P) Mod MuMB
  1491. void MultiSI::RPowMB( MultiSI& P)
  1492. // P may have the same address in memory as this
  1493. // P is not changed unless it shares memory with this
  1494. // Sets MuErr True if overflow or error
  1495. {
  1496.   PowMB( *this, P);
  1497. } // --end-- // MultiSI::RPowMB()
  1498.  
  1499. // ------- this = Greatest common divisor A, B
  1500. void MultiSI::GCD( MultiSI& A, MultiSI& B)
  1501. // A, B are not modified unless they share memory with this
  1502. // Will write to standard output if MuErrRep is True
  1503. {
  1504.   MultiSI AL(A.N);  AL.SetTo(A);
  1505.   MultiSI BL(B.N);  BL.SetTo(B);
  1506.   Bool Fini = False;
  1507.   AL.S = False;  BL.S = False;
  1508.   if (AL.ZTest()) { SetTo( BL);  Fini = True; }
  1509.   if (BL.ZTest()) { SetTo( AL);  Fini = True; }
  1510.   int NN = 0;
  1511.   if (MuErrRep && !Fini)  cout << nL;
  1512.   while (!Fini) {
  1513.     NN++;
  1514.     if (NN % 2) {
  1515.       AL.Modu( AL, BL);
  1516.       if (MuErrRep) {
  1517.     cout << NN << ' ';  AL.WritLn( cout);
  1518.       }
  1519.       if (AL.ZTest()) { SetTo( BL);  Fini = True; }
  1520.     } else {
  1521.       BL.Modu( BL, AL);
  1522.       if (MuErrRep) {
  1523.     cout << NN << ' ';  BL.WritLn( cout);
  1524.       }
  1525.       if (BL.ZTest()) { SetTo( AL);  Fini = True; }
  1526.     }
  1527.   }
  1528. } // --end-- // MultiSI::GCD()
  1529.  
  1530. // ------- this=Greatest common divisor A, this
  1531. void MultiSI::RGCD( MultiSI& A)
  1532. // A is not modified unless it shares memory with this
  1533. // Will write to standard output if MuErrRep is True
  1534. {
  1535.   GCD(A, *this);
  1536. } // --end-- // MultiSI::RGCD()
  1537.  
  1538. // ------- this = (X !) Mod MuMB = 1*2*3*...*X
  1539. void MultiSI::FacMB( MultiSI& X)
  1540. // X may have the same address in memory as this
  1541. // X is not changed unless it shares memory with this
  1542. // Sets MuErr True if overflow or error
  1543. {
  1544.   double NN;
  1545.   if (X.S) {
  1546.     MuWriteErr("Cannot take factorial of number < zero");
  1547.     Clear();  return;
  1548.   }
  1549.   if (X.N > 2) {
  1550.     MuWriteErr("Number too large for factorial function");
  1551.     Clear();  return;
  1552.   }
  1553.   MultiSI XL(X.N);  XL.SetTo(X);
  1554.   SetTo1(1);
  1555.   XL.GetD( NN);
  1556.   while (NN > 1) {
  1557.     Mul( XL, *this);
  1558.     ModMB();
  1559.     if (MuAbort) {
  1560.       Clear();  return;
  1561.     }
  1562.     NN--;
  1563.     XL.SetToD( NN);
  1564.   }
  1565. } // --end-- // MultiSI::FacMB()
  1566.  
  1567. // ------- this = (this !) Mod MuMB = 1*2*3*...*X
  1568. void MultiSI::RFacMB()
  1569. // Sets MuErr True if overflow or error
  1570. {
  1571.   FacMB( *this);
  1572. } // --end-- // MultiSI::RFacMB()
  1573.  
  1574. // ------- this = SqRt(X), R = Rem, Slow Method (but fast for small numbers)
  1575. void MultiSI::SqRtRemSlow( MultiSI& X, MultiSI& R)
  1576. // X is not changed, X is moved to R and then R is "divided"
  1577. // in place to give the SqRt in this and a remainder in R, it is OK for X and R
  1578. // or X and this to have the same location in memory, but then X will be changed
  1579. // this and R may not have the same location in memory. Sets MuErr True if error
  1580. {
  1581.   Mu1Digit D0, QH;
  1582.   Mu2Digit T, T2, D4, K;
  1583.   long i, j, RI0, DI0, RI, DI, ij;
  1584.   if (V == NULL)  NMax( max( 1+X.N/2, 3));  // V and R.V may be NULL
  1585.   if (V == R.V) {
  1586.     MuWriteErr(
  1587.   "Cannot set same location to both square root and remainder, continuing...");
  1588.     return;
  1589.   }
  1590.   R.SetTo(X);
  1591.   Clear();
  1592.   if (R.S) {
  1593.     MuWriteErr("Cannot take square root of negative number, continuing...");
  1594.     R.Clear();  return;
  1595.   }
  1596.   if (M < 3)  NMax(3);
  1597.   if (R.M < 4)  R.NMax(4);
  1598.   if (R.N < 4) {
  1599.     for (i = R.N; i <= 3; i++)  R.V[i] = 0;
  1600.     R.N = 4;
  1601.   }
  1602.   if (R.N % 2) {
  1603.     R.V[R.N] = 0;
  1604.     R.N++;
  1605.   }
  1606.   N = R.N / 2 + 1;
  1607.   T = 0;
  1608.   for (i = 1; i <= 4; i++)  T = T * Base + R.V[R.N - i];
  1609.   T2 = floor( sqrt(T));
  1610.   do {
  1611.     D0 = floor( T2 / Base);
  1612.     QH = 1 + T2 - D0 * Base; // +1 for safety
  1613.     T = R.V[R.N - 1] * Base + R.V[R.N - 2] - D0 * D0;
  1614.     if (T < 0)  T2--;
  1615.   } while (T < 0);
  1616.   K = floor(T / Base);
  1617.   R.V[R.N - 2] = T - K * Base;
  1618.   R.V[R.N - 1] = K;
  1619.   if (N >= 4)  V[N - 4] = 0;
  1620.   V[N - 3] = QH;
  1621.   T = 2 * D0;
  1622.   K = floor(T / Base);
  1623.   V[N - 2] = T - K * Base;
  1624.   V[N - 1] = K;
  1625.   KeyHit = False;
  1626.   for (j = 2; j <= R.N / 2; j++) {
  1627.     K = Base;  RI0 = R.N - j - j;  DI0 = N - j - 1;
  1628.     RI = RI0;   DI = DI0;   ij = RI0 + j;
  1629.     while (RI <= ij) {    // Multiply and subtract
  1630.       T = R.V[RI] - QH * V[DI] + K + BSMB; // + BaseSq - Base
  1631.       K = floor(T / Base);
  1632.       T -= K * Base;
  1633.       R.V[RI] = T;
  1634.       RI++;  DI++;
  1635.     }
  1636.     T = R.V[RI] + K + BSMB; // + BaseSq - Base
  1637.     K = floor(T / Base);
  1638.     R.V[RI] = T - K * Base;
  1639.     while (K == MaxDigit) { // Test remainder
  1640. // WriteLn("MuSqRt: Doing an add back"); .Diag for add back test
  1641.       QH--;    // Add back
  1642.       K = QH;  RI = RI0;  DI = DI0;
  1643.       while (RI <= ij) {
  1644.     T = R.V[RI] + V[DI] + K;
  1645.     K = floor(T / Base);
  1646.     R.V[RI] = T - K * Base;
  1647.     RI++;  DI++;
  1648.       }
  1649.       T = R.V[RI] + K;
  1650.       K = floor(T / Base);
  1651.       R.V[RI] = T - K * Base;
  1652.       K += MaxDigit;
  1653.       V[DI0] = QH;
  1654.     }
  1655.     i = DI0;  ij = i + j;  K = QH;
  1656.     while (i <= ij) {
  1657.       T = V[i] + K;         // Carry to next super digit
  1658.       K = floor(T / Base);
  1659.       V[i] = T - K * Base;
  1660.       if (!K)  i = ij;    // Break out of loop
  1661.       i++;
  1662.     }
  1663.     if (j < R.N / 2) {
  1664.       T = 0;
  1665.       for (i = 0; i <= 4; i++) {
  1666.     T = T * Base + R.V[R.N - j - i];
  1667.       }
  1668.       D4 = 0;
  1669.       for (i = 1; i <= 4; i++) {
  1670.     D4 = D4 * Base + V[N - i];
  1671.       }
  1672.       QH = 1 + floor(T / D4);
  1673.       V[N - j - 2] = QH;
  1674.     }
  1675.     MuInterrupt();
  1676.     if (MuAbort) {
  1677.       Clear();  R.Clear();  return;
  1678.     }
  1679.     if (KeyHit) {
  1680.       cout << "Integer Square Root: "
  1681.        << floor( 400.0 * j * j / R.N / R.N) << " Percent done" << nL;
  1682.       KeyHit = False;
  1683.     }
  1684.   }
  1685.   R.N = R.N / 2 + 1;
  1686.   R.Norm();
  1687.   Norm();
  1688.   IpDiv1( *this, 2, QH);
  1689. } // --end-- // MultiSI::SqRtRemSlow()
  1690.  
  1691. // ------- this = SqRt(X), R = Rem, Fast method for large numbers
  1692. void MultiSI::SqRtRemFast( MultiSI& X, MultiSI& R)
  1693. // X is not changed, X is moved to R and then R is "divided"
  1694. // in place to give the SqRt in this and a remainder in R, it is OK for X and R
  1695. // or X and this to have the same location in memory, but then X will be changed
  1696. // this and R may not have the same location in memory. Sets MuErr True if error
  1697. {
  1698.   MultiSI XL;  // Local X
  1699.   MultiSI YL;  // Local Y = SqRt(X)
  1700.   MultiSI Q;   // Q = XL / YL
  1701.   MultiSI RL;  // Local remainder
  1702.   MultiSI T;   // 2 * YL
  1703.   MultiSI D;   // RL / T
  1704.   MultiSI TD;  // T * D
  1705.   long    i, j, pl, po, ps, xs, ys, qs; //Scalings, X = XL * Base^xs
  1706.   Bool adjusted; // True iff an adjustment was needed
  1707.  
  1708.   pl = 5;
  1709.   ps = pl+pl+2;
  1710.   if (X.N % 2)  ps--; // ps = pl+pl+1
  1711.   if (X.N < ps || X.S) { SqRtRemSlow(X, R);  return; }
  1712.   XL.N = XL.M = ps;
  1713.   XL.V = X.V + (X.N-ps);
  1714.   YL.NMax( pl+2);
  1715.   RL.NMax( ps);
  1716.   YL.SqRtRemSlow( XL, RL);  RL.NMax(1);
  1717.   XL.V = NULL;
  1718.   ys = (X.N - ps) / 2;
  1719.  
  1720.   while (pl <= (X.N / 2)) { // y = (y + x / y) / 2
  1721.     po = pl;  pl += pl;
  1722.     if (pl > (X.N / 2))  pl = 1 + X.N / 2;
  1723.     j = pl+po+2;
  1724.     if (j > X.N)  j = X.N;
  1725.     XL.N = XL.M = j;
  1726.     XL.V = X.V + (X.N-j);
  1727.     xs = X.N - XL.N;
  1728.     Q.NMax( 1 + XL.N - YL.N);
  1729.     RL.NMax( XL.N);
  1730.     IpDiv( XL, YL, Q, RL);  XL.V = NULL;  RL.NMax(1);
  1731.     qs = xs - ys;
  1732.     if (ys > qs) {
  1733.       for (j = YL.N-1, i = j + ys-qs,  YL.NMax( i+2), YL.N = i+1;
  1734.        i >= 0;  i--, j--) {
  1735.     if (j >= 0)
  1736.       YL.V[i] = YL.V[j];
  1737.     else
  1738.       YL.V[i] = 0;
  1739.       }
  1740.       ys = qs;
  1741.     }
  1742.     if (ys < qs)
  1743.       FatalErr("ys < qs in MultiSI::SqRtRemFast()");
  1744.     YL.RAdd(Q);  Q.NMax(1);
  1745.     YL.RDiv1(2);
  1746.     if (ys < 0) {
  1747.       for (i = 0, j = -ys, YL.N -= j; i < YL.N;  i++, j++)  YL.V[i] = YL.V[j];
  1748.       ys = 0;
  1749.     }
  1750.   }
  1751.  
  1752.   XL.NMax( YL.N + YL.N);
  1753.   XL.Mul( YL, YL);
  1754.   RL.NMax( X.N + 1);
  1755.   RL.Sub( X, XL);  XL.NMax(1);
  1756.   T.NMax( YL.N + 1);
  1757.   T.Add( YL, YL);
  1758.  
  1759.   adjusted = False;
  1760.   while (RL.S || RL.Comp(T) > 0) {
  1761.     adjusted = True;
  1762.     if (RL.S) {
  1763.       if (T.N > RL.N)  { D.NMax(1);  D.Clear(); }
  1764.       else {
  1765.     RL.S = Plus;
  1766.     D.NMax(1 + RL.N - T.N);
  1767.     D.Divi( RL, T);
  1768.     RL.S = Minus;
  1769.       }
  1770.       D.RAdd1(1);
  1771.       T.RSub( D);
  1772.       TD.NMax( T.N + D.N);
  1773.       TD.Mul( T, D);
  1774.       RL.RAdd( TD);  TD.NMax(1);
  1775.       T.RSub( D);
  1776.     }
  1777.  
  1778.     else if (RL.Comp(T) > 0) {
  1779.       D.NMax( 1 + RL.N - T.N);
  1780.       D.Divi( RL, T);
  1781.       T.RAdd( D);
  1782.       TD.NMax( T.N + D.N);
  1783.       TD.Mul( T, D);
  1784.       RL.RSub( TD);  TD.NMax(1);
  1785.       T.RAdd( D);
  1786.     }
  1787.   }
  1788.  
  1789.   if (adjusted)  YL.Div1(T, 2);
  1790.   if (R.V == NULL)  R >>= RL;  // If R not allocated, swap with RL
  1791.     else            R <<= RL;  // else set to RL (copy)
  1792.   if (V == NULL)  *this >>= YL;
  1793.     else          *this <<= YL;
  1794. } // --end-- // MultiSI::SqRtRemFast()
  1795.  
  1796. // ------- this = SqRt(X), R = Rem
  1797. void MultiSI::SqRtRem( MultiSI& X, MultiSI& R)
  1798. // X is not changed, X is moved to R and then R is "divided"
  1799. // in place to give the SqRt in this and a remainder in R, it is OK for X and R
  1800. // or X and this to have the same location in memory, but then X will be changed
  1801. // this and R may not have the same location in memory. Sets MuErr True if error
  1802. {
  1803.   if (X.N <= 2024)
  1804.     SqRtRemSlow(X, R);
  1805.   else
  1806.     SqRtRemFast(X, R);
  1807. } // --end-- // MultiSI::SqRtRem()
  1808.  
  1809. // ------- this = SqRt( this), R = Rem
  1810. void MultiSI::RSqRtRem( MultiSI& R)
  1811. // this is moved to R and then R is "divided" in place to give the SqRt in this
  1812. // and a remainder in R, this and R may not have the same location in memory
  1813. // Sets MuErr True if error
  1814. {
  1815.   SqRtRem( *this, R);
  1816. } // --end-- // MultiSI::RSqRtRem()
  1817.  
  1818. // ------- this = SqRt(X)
  1819. void MultiSI::SqRoot( MultiSI& X)
  1820. // X is not changed, it is OK for X and this to have the same location in memory
  1821. // but then X will be changed.  Sets MuErr True if error
  1822. {
  1823.   MultiSI RL(X.N);
  1824.   SqRtRem(X, RL);
  1825. } // --end-- // MultiSI::SqRoot()
  1826.  
  1827. // ------- this = SqRt( this)
  1828. void MultiSI::RSqRt()
  1829. // Sets MuErr True if error
  1830. {
  1831.   SqRoot( *this);
  1832. } // --end-- // MultiSI::RSqRt()
  1833.  
  1834. // ------- this = Read MultiSI from a file
  1835. void MultiSI::ReadSI( FILE* R, char* Name, Bool& OK)
  1836. // Returns Name and OK != 0 if read is OK
  1837. // MuErr set True if overflow
  1838. {
  1839.   char ch;
  1840.   long Li, Lj, Len = 0;
  1841.   int j = 0;
  1842.   Bool S = False; // Boolean
  1843.   Bool OverFlow = False; // Boolean
  1844.   Mu1Digit Dig, SDig = 0;
  1845.   Clear();  N = 0;  Name[0] = NULL;  OK = False;  TracN = 0;
  1846.   do {
  1847.     ch = fgetc(R);
  1848.     if (ch == '=')  break;
  1849.     if (ch == '\n') { j = 0;  Name[0] = NULL; }
  1850.     else
  1851.       Name[j++] = ch;
  1852.   } while (ch != EOF);
  1853.   Name[j] = NULL;
  1854.   if (ch == EOF)  return;
  1855.   do {
  1856.     ch = fgetc(R);
  1857.     if ((ch == ' ') || (ch == '\n') || (ch == '\t'))  ;
  1858.     else if (ch == '-')  { S = True;  break; }
  1859.     else if (ch == '+')  break;
  1860.     else if ((ch >= '0') && (ch <= '9')) {
  1861.       ungetc( ch, R);  break;
  1862.     }
  1863.   } while (ch != EOF);
  1864.   if (ch == EOF)  return;
  1865.   do {
  1866.     ch = fgetc(R);
  1867.     if ((ch == ',') || (ch == '\n'))  ;
  1868.     else if ((ch >= '0') && (ch <= '9')) {
  1869.       OK = True;
  1870.       TracN++;  Trace = ++Len;
  1871.       Dig = (ch - '0');
  1872.       SDig = 10 * SDig + Dig;
  1873.       if (!(Len % MuDMax)) {
  1874.     N++;
  1875.     if ((Li = M - N) < 0) // HJS 1992-12-13 (was <= 0)
  1876.       { OverFlow = True;  N = M;  Li = 0;  SDig = 0;  break; }
  1877.     V[Li] = SDig;  SDig = 0;
  1878.       }
  1879.       MuInterrupt();  if (MuAbort)  break;
  1880.     }
  1881.     else  break;
  1882.   } while (ch != EOF);
  1883.   for (Lj = 0;  Lj < N;  Li++, Lj++)  V[Lj] = V[Li];
  1884.   for (j = (int)(Len % MuDMax), Dig = 1;  j > 0;  j--)  Dig = Dig * 10;
  1885.   RMul1( Dig);  RAdd1( SDig);
  1886.   if (S)  ChS();
  1887.   if (OverFlow)  MuWriteErr("Input number overflow, continuing...");
  1888.   Norm();
  1889. } // --end-- MultiSI::ReadSI()
  1890.  
  1891. // --end-- MultiSI's method implementation
  1892.  
  1893. // --end-- Method implementation
  1894.  
  1895. // ------- Other services
  1896.  
  1897. // ------- Check far heap  // Heap check not supported by MS Windows
  1898. Bool HeapOk() {
  1899. //  if( farheapcheck() == _HEAPCORRUPT ) ???
  1900. //    { cout << "Heap is corrupted.\n";  return False; }
  1901. //  else
  1902. //    { cout << "Heap is OK.\n";  return True; }
  1903.   return True;
  1904. } // --end-- HeapOk()
  1905.  
  1906. // ------- Diag for a MultiSI
  1907. void DiagSI( char* St, MultiSI& X)
  1908. {
  1909.   if (LogF.good()) {
  1910.     if (MuErr)  LogF << "MuErr = True\n";
  1911.     LogF << St << " (" << X.M << ", " << X.N << ") =\n" << X << dL; MuTot = 0;
  1912.     LogF << flush;
  1913.   }
  1914. } // --end-- DiagSI
  1915.  
  1916. // ------- Fatal error handler
  1917. //           from Numerical Recipes standard error handler (see page 705)
  1918. void FatalErr( char error_text[])
  1919. {
  1920.   fprintf( stderr, "Fatal run-time error...\n");
  1921.   fprintf( stderr, "%s\n", error_text);
  1922.   fprintf( stderr, "...now exiting to system...\n");
  1923.   exit(1);
  1924. } // --end-- FatalErr()
  1925.  
  1926. // ------- Allocates a bytes8 vector with range [nl..nh] (see page 705)
  1927. bytes8 huge *vector8( long nl,  long nh)
  1928. {
  1929.   bytes8 huge *v;
  1930.   v = (bytes8 huge *) farcalloc( (nh-nl+1), sizeof( bytes8));
  1931.   if (!v)  return v;
  1932.   if (kbhit()) {
  1933.     MuInterrupt();  KeyHit = False;
  1934.     cout << "vector8: Allocated array[" << nl << ".." << nh << ']' << nL;
  1935.   }
  1936.   v = v-nl;
  1937.   return v;
  1938. } // --end-- vector8()
  1939.  
  1940. // ------- Frees a bytes8 vector allocated by vector8() (see page 707)
  1941. void free_vector8( bytes8 huge *v,  long nl,  long nh)
  1942. {
  1943.   bytes8 huge *vl;
  1944.   vl = v+nl;
  1945.   if (v) farfree( vl);  nh;
  1946. } // --end-- free_vector8()
  1947.  
  1948. // ------- FFT of complex type data (see page 411)
  1949. void four1( bytes8 huge *data,  long nn,  Bool isign)
  1950. /*
  1951.    Replace data by its discrete Fourier transform, if isign is input as 1;
  1952.    or replace data by nn times its inverse discrete Fourier transform, if
  1953.    isign is input as -1.  data is a complex array of length nn, input as a
  1954.    real array data[1..2*nn].  nn must be an integer power of 2 (this is not
  1955.    checked for!).
  1956. */
  1957. {
  1958.   #define SWAP(a, b)  tempr = (a);  (a) = (b);  (b) = tempr;
  1959.   long n, mmax, m, j, istep, i;
  1960.                // Double precision for trigonometric recurrences.
  1961.   RealPlus wtemp, wr, wpr, wpi, wi, theta;
  1962.   Real tempr, tempi;
  1963.  
  1964.   n = nn << 1;
  1965.   j = 1;
  1966.   for (i = 1; i < n; i += 2) {
  1967.     if (j > i) {          // This is the bit-reversal section of the routine.
  1968.       SWAP( data[j].v,   data[i].v);     // Exchange the two complex numbers.
  1969.       SWAP( data[j+1].v, data[i+1].v);
  1970.     }
  1971.     m = n >> 1;
  1972.     while (m >= 2 && j > m) {
  1973.       j -= m;
  1974.       m >>= 1;
  1975.     }
  1976.     j += m;
  1977.  
  1978.     if (!((i+1) % 1000)) {
  1979.       if (kbhit()) {
  1980.     MuInterrupt();  KeyHit = False;
  1981.     if (MuAbort)  return;
  1982.     cout << "four1: bit-reversal section, i = " << (i+1) << " of " << n
  1983.          << nL;
  1984.       }
  1985.     }
  1986.   }
  1987.   mmax = 2;      // Here begins the Danielson-Lanczos section of the routine.
  1988.   while (mmax < n) {                    // Outer loop executed log2 nn times.
  1989.     istep = 2 * mmax;
  1990.     theta = Pi2 / (isign * mmax);//Initialize for the trigonometric recurrence.
  1991.     wtemp = sinl( 0.5 * theta);
  1992.     wpr = -2.0 * wtemp * wtemp;
  1993.     wpi = sinl( theta);
  1994.     wr = 1.0;
  1995.     wi = 0.0;
  1996.     for (m = 1; m < mmax; m += 2) { // Here are the two nested inner loops.
  1997.       for (i = m; i <= n; i += istep) {
  1998.     j = i + mmax;               // This is the Danielson-Lanczos formula.
  1999.     tempr = wr * data[j].v   - wi * data[j+1].v;
  2000.     tempi = wr * data[j+1].v + wi * data[j].v;
  2001.     data[j].v   = data[i].v   - tempr;
  2002.     data[j+1].v = data[i+1].v - tempi;
  2003.     data[i].v   += tempr;
  2004.     data[i+1].v += tempi;
  2005.       }                                          // Trigonometric recurrence.
  2006.       wr = (wtemp = wr) * wpr - wi * wpi + wr;
  2007.       wi = wi * wpr + wtemp * wpi + wi;
  2008.     }
  2009.     mmax = istep;
  2010.  
  2011.     if (kbhit()) {
  2012.       MuInterrupt();  KeyHit = False;
  2013.       if (MuAbort)  return;
  2014.       cout << "four1: istep = " << istep << " of " << n << nL;
  2015.     }
  2016.   }
  2017. } // --end-- four1()
  2018.  
  2019. // ------- Two FFTs of real data for the price of one (see page 415)
  2020. void twofft( bytes8 huge *data1,  bytes8 huge *data2,  bytes8 huge *fft1,
  2021.          bytes8 huge *fft2,   long n)
  2022. /*
  2023.    Given two input arrays data1[1..n] and data2[1..n], this routine calls
  2024.    four1 and returns two complex output arrays, fft1 and fft2, each of
  2025.    complex length n (i.e. real dimensions [1..2n]), which contains the
  2026.    discrete Fourier transform of the respective data.  n MUST be an integer
  2027.    power of 2.
  2028. */
  2029. {
  2030.   long nn3, nn2, jj, j;
  2031.   Real rep, rem, aip, aim;
  2032.  
  2033.   nn3 = 1 + (nn2 = 2 + n + n);
  2034.   for (j= 1, jj = 2;  j <= n;  j++, jj += 2) {
  2035.     fft1[jj-1].v = data1[j].v; //Pack the 2 real arrays into 1 complex array.
  2036.     fft1[jj  ].v = data2[j].v;
  2037.  
  2038.     if (!(j % 1000)) {
  2039.       if (kbhit()) {
  2040.     MuInterrupt();  KeyHit = False;
  2041.     if (MuAbort)  return;
  2042.     cout << "twoft: Pack the 2 real arrays into 1 complex array, j = "
  2043.          << j << " of " << n << nL;
  2044.       }
  2045.     }
  2046.   }
  2047.   four1( fft1, n, 1);      // Transform the complex array
  2048.   if (MuAbort)  return;
  2049.   fft2[1].v = fft1[2].v;
  2050.   fft1[2].v = fft2[2].v = 0.0;
  2051.   for (j = 3; j <= n+1; j += 2) {
  2052.     rep = 0.5 * (fft1[j].v   + fft1[ nn2 - j].v);//Use symmetries to separate
  2053.     rem = 0.5 * (fft1[j].v   - fft1[ nn2 - j].v);//  the two transforms.
  2054.     aip = 0.5 * (fft1[j+1].v + fft1[ nn3 - j].v);
  2055.     aim = 0.5 * (fft1[j+1].v - fft1[ nn3 - j].v);
  2056.     fft1[j].v     = rep;
  2057.     fft1[j+1].v   = aim;
  2058.     fft1[nn2-j].v = rep;
  2059.     fft1[nn3-j].v = -aim;
  2060.     fft2[j].v     = aip;
  2061.     fft2[j+1].v   = -rem;
  2062.     fft2[nn2-j].v = aip;
  2063.     fft2[nn3-j].v = rem;
  2064.  
  2065.     if (!((j+1) % 1000)) {
  2066.       if (kbhit()) {
  2067.     MuInterrupt();  KeyHit = False;
  2068.     if (MuAbort)  return;
  2069.     cout << "twoft: Separate the two transforms, j = "
  2070.          << (j+1) << " of " << n << nL;
  2071.       }
  2072.     }
  2073.   }
  2074. } // --end-- twofft()
  2075.  
  2076. // ------- FFT of real data (see page 417)
  2077. void realft( bytes8 huge *data,  long n,  Bool isign)
  2078. /*
  2079.    Calculates the Fourier Transform of a set of 2n real-valued data points.
  2080.    Replaces this data (which is stored in array data[1..2n]) by the positive
  2081.    frequency half of its complex Fourier Transform.  The real-valued first
  2082.    and last components of the complex transform are returned as elements
  2083.    data[1] and data[2] respectively.  n must be a power of 2.  This routine
  2084.    also calculates the inverse transform of a complex data array if it is the
  2085.    transform of real data.  (Result in this case must be multiplied by 1/n.)
  2086. */
  2087. {
  2088.   long i, i1, i2, i3, i4, n2p3;
  2089.   Real c1 = 0.5, c2, h1r, h1i, h2r, h2i;
  2090.   RealPlus wr, wi, wpr, wpi, wtemp, theta; // Extra precision for
  2091.                        //   trigonometric recurrences.
  2092.   theta = Pi / (double) n;                 // Initialize the recurrence.
  2093.   if (isign == 1) {
  2094.     c2 = -0.5;
  2095.     four1( data, n, 1);                  // The forward transform is here
  2096.     if (MuAbort)  return;
  2097.   } else {
  2098.     c2 = 0.5;                      // Otherwise set up the inverse transform.
  2099.     theta = -theta;
  2100.   }
  2101.   wtemp = sinl( 0.5 * theta);
  2102.   wpr = -2.0 * wtemp * wtemp;
  2103.   wpi = sinl( theta);
  2104.   wr = 1.0 + wpr;
  2105.   wi = wpi;
  2106.   n2p3 = 2 * n + 3;
  2107.   for (i = 2; i <= n / 2; i++) {         // Case i = 1 done separately below.
  2108.     i4 = 1 + (i3 = n2p3 - (i2 = 1 + (i1 = i + i - 1)));
  2109.     h1r = c1 * (data[i1].v + data[i3].v);  // The two separate transforms are
  2110.     h1i = c1 * (data[i2].v - data[i4].v);  //   separated out of data.
  2111.     h2r =-c2 * (data[i2].v + data[i4].v);
  2112.     h2i = c2 * (data[i1].v - data[i3].v);
  2113.     data[i1].v = h1r + wr * h2r - wi * h2i;//Here they are recombined to form
  2114.     data[i2].v = h1i + wr * h2i + wi * h2r;//  the true transform of the
  2115.     data[i3].v = h1r - wr * h2r + wi * h2i;//  original real data.
  2116.     data[i4].v =-h1i + wr * h2i + wi * h2r;
  2117.     wr = (wtemp = wr) * wpr - wi * wpi + wr;   // The recurrence.
  2118.     wi = wi * wpr + wtemp * wpi + wi;
  2119.  
  2120.     if (!(i % 1000)) {
  2121.       if (kbhit()) {
  2122.     MuInterrupt();  KeyHit = False;
  2123.     if (MuAbort)  return;
  2124.     cout << "realft: separate and recombine transforms, i = "
  2125.         << i << " of " << n/2 << nL;
  2126.       }
  2127.     }
  2128.   }
  2129.   if (isign == 1) {
  2130.     data[1].v = (h1r = data[1].v) + data[2].v; // Squeeze the first and last data
  2131.     data[2].v =  h1r - data[2].v;        //   together to get them all within
  2132.                      //   the original array.
  2133.   } else {
  2134.     data[1].v = c1 * ((h1r = data[1].v) + data[2].v);
  2135.     data[2].v = c1 *  (h1r - data[2].v);
  2136.     four1( data, n, -1);                 // This is the inverse transform for
  2137.                      //   the case isign = -1.
  2138.     if (MuAbort)  return;
  2139.   }
  2140. } // --end-- realft()
  2141.  
  2142. // ------- Convolves or deconvolves a real data set (see page 430)
  2143. void convlv( bytes8 huge *data,    long n,
  2144.          bytes8 huge *respns,  long m,
  2145.          Bool isign,           bytes8 huge *ans,
  2146.          bytes8 huge *fft)
  2147. /*
  2148.    Convolves or deconvolves a real data set data[1..n] (including any user-
  2149.    supplied zero padding) with a response function respns[1..n].  The
  2150.    response function must be stored in wrap around order in the first m
  2151.    elements of respns, where m is an odd integer <= n.  Wrap around order
  2152.    means that the first half of the array respns contains the impulse
  2153.    response function at positive times, while the second half of the array
  2154.    contains the impulse response function at negative times, counting down
  2155.    from the highest element respns[m].  On input isign is +1 for convolution,
  2156.    -1 for deconvolution.  The answer is returned in the first n components of
  2157.    ans.  However, ans must be supplied in the calling program with dimensions
  2158.    [1..2*n], for consistency with twofft.  n MUST be an integer power of two.
  2159.    Note: if (m <= 0) respns is assumed to have user supplied zero padding.
  2160.      Must allocate fft[1..2n] for temp storage before calling:
  2161.        fft = vector8(1, 2 * n);
  2162.      data[] and respns[] can be overlaid with ans[] by allocating them
  2163.      as the same memory locations:
  2164.     ans    = vector8(1, 2 * n);
  2165.     fft    = vector8(1, 2 * n);
  2166.     data   = ans;
  2167.     respns = ans + n;
  2168. */
  2169. {
  2170.   #define SQR(a)    (sqrarg=(a), sqrarg*sqrarg)
  2171.   static Real sqrarg;
  2172.   long i, no2;
  2173.   Real dum, mag2;
  2174.  
  2175.   if (m > 0) {
  2176.     for (i = 1; i <= (m-1) / 2; i++)     // Put respns in array of length n.
  2177.       respns[n + 1 - i].v = respns[m + 1 - i].v;
  2178.     for (i = (m + 3) / 2; i <= n - (m - 1) / 2; i++)    // Pad with zeros.
  2179.       respns[i].v = 0.0;
  2180.   }
  2181.   twofft( data, respns, fft, ans, n);    // FFT both at once
  2182.   if (MuAbort)  return;
  2183.   no2 = n / 2;
  2184.   for (i = 2; i <= n + 2; i += 2) {
  2185.     if (isign == 1) {                    // Multiply FFTs to convolve.
  2186.       ans[i-1].v = (fft[i-1].v * (dum=ans[i-1].v) - fft[i].v * ans[i].v)/no2;
  2187.       ans[i].v = (fft[i].v * dum + fft[i-1].v * ans[i].v) / no2;
  2188.     }
  2189.     else if (isign == -1) {
  2190.       if ((mag2 = SQR( ans[i-1].v) + SQR( ans[i].v)) == 0.0)
  2191.     FatalErr("Deconvolving at response zero in CONVLV");
  2192.                      // Divide FFTs to deconvolve.
  2193.       ans[i-1].v = (fft[i-1].v*(dum=ans[i-1].v) + fft[i].v*ans[i].v)/mag2/no2;
  2194.       ans[i].v = (fft[i].v * dum - fft[i-1].v * ans[i].v) / mag2 / no2;
  2195.     }
  2196.     else FatalErr("No meaning for ISIGN in CONVLV");
  2197.  
  2198.     if (!(i % 1000)) {
  2199.       if (kbhit()) {
  2200.     MuInterrupt();  KeyHit = False;
  2201.     if (MuAbort)  return;
  2202.     cout << "convov: Multiply FFTs to convolve, i = "
  2203.          << i << " of " << n << nL;
  2204.       }
  2205.     }
  2206.   }
  2207.   ans[2].v = ans[n+1].v;          // Pack last element with first for realft.
  2208.   realft( ans, no2, -1);          // Inverse transform back to time domain.
  2209.   if (MuAbort)  return;
  2210. } // --end-- convlv()
  2211.  
  2212. // ------- MuWriteErr, write error statement and set error flag
  2213. void MuWriteErr( char *St)
  2214. // Allows St to be a literal string
  2215. {
  2216.   MuErr = True;
  2217.   if (MuErrRep) {
  2218.     cout << St << nL;
  2219.     if (Echo)
  2220.       LogF << St << nL;
  2221.   }
  2222. } // --end-- MuWriteErr
  2223.  
  2224. // ------- Read in string from an istream, allow a blank line
  2225. void ReadSt( istream& In, char *St)
  2226. {
  2227.   In.get( St, 81);
  2228.   if (In.peek() == '\n')  In.get(); // Clear '\n' from input
  2229. } // --end-- // ReadSt istream
  2230.  
  2231. // ------- Read in string from the key board, allow a blank line
  2232. void ReadSt( char *St)
  2233. {
  2234.   cin.get( St, 81);
  2235.   if (cin.peek() == '\n')  cin.get(); // Clear '\n' from input
  2236. } // --end-- // ReadSt
  2237.  
  2238. // ------- Read in a long integer from keyboard
  2239. void ReadLInt( char *Mess, long Min, long Max, long Nom,
  2240.            long& II)
  2241. {
  2242.   char St[81];
  2243.   int  Stat;
  2244.   long LI;
  2245.   do {
  2246.     cout << Mess << nL;
  2247.     cout << "  [" << Min << ", " << Max << "] (ENTER => " << Nom << "): ";
  2248.     ReadSt( St);
  2249.     Stat = sscanf( St, "%ld", &LI);
  2250.   } while (((Stat != 1) || (LI < Min) || (LI > Max)) && (St[0] != '\0'));
  2251.   if (St[0] == '\0')  LI = Nom;
  2252.   II = LI;
  2253.   cout << "Input = " << II << nL;
  2254. } // --end-- // ReadLInt
  2255.  
  2256. // ------- // Read in an integer from keyboard
  2257. void ReadInt( char *Mess, int Min, int Max, int Nom, int& II)
  2258. {
  2259.   char St[81];
  2260.   int Stat;
  2261.   long LI;
  2262.   do {
  2263.     cout << Mess << nL;
  2264.     cout << "  [" << Min << ", " << Max << "] (ENTER => " << Nom << "): ";
  2265.     ReadSt( St);
  2266.     Stat = sscanf( St, "%ld", &LI);
  2267.   } while (((Stat != 1) || (LI < Min) || (LI > Max)) && (St[0] != '\0'));
  2268.   if (St[0] == '\0')  LI = Nom;
  2269.   II = (int)LI;
  2270.   cout << "Input = " << II << nL;
  2271. } // --end-- // ReadInt
  2272.  
  2273. // ------- Set MMax
  2274. void MuSetMMax( int NRegs)
  2275. {
  2276.   int Percent;
  2277.   long Max = 300000L; // Arbitrary number of max bytes to be used
  2278.   cout << "MemAvail = " << Max << " bytes" << nL;
  2279.   if (Echo)  LogF << "MemAvail = " << Max << " bytes" << nL;
  2280.   ReadInt("Input % of available memory to use:", 0, 100, 100, Percent);
  2281.   Max = ((Max - 256) * Percent) / (100 * NRegs); // Max per register
  2282.   MMax = (Max - sizeof( MultiSI)) / sizeof( Mu1Digit) - 1;
  2283.   if (MMax > MuNMax)  MMax = MuNMax;
  2284.   if (MMax < 5)  MMax = 5;
  2285. } // --end-- MuSetMMax
  2286.  
  2287. // ------- Test for ESC key pressed to abort operation
  2288. void MuInterrupt()
  2289. // MuAbort set TRUE if ESC pressed twice, unchanged if no ESC or ESC, SPACE
  2290. {
  2291.   char Esc = 27; // ESCAPE
  2292.   char Ret = 13; // RETURN
  2293.   char Ch;
  2294.   if (!kbhit())  return;
  2295.   while (kbhit())  Ch = getch();
  2296.   KeyHit = True;  KeyCh = Ch;  DosClock();
  2297.   if (Trace > 0) {
  2298.     cout << '<' << TracN << ' ' << Trace << '>' << nL;
  2299.     Trace = 0;
  2300.   }
  2301.   if ((Ch != Esc) || MuAbort)  return;
  2302.   cout << "*** INTERRUPT:  To Continue Press RETURN Key;\n";
  2303.   cout << "To Abort Computation Press ESCAPE Key;\n";
  2304.   cout << "To Set SoftAbort Flag Press SPACE Bar.\n\n";
  2305.   do {Ch = getch();} while ((Ch != Esc) && (Ch != Ret) && (Ch != ' '));
  2306.   if (Ch == Ret)  cout << "Continuing...\n";
  2307.   if (Ch == Esc) {
  2308.     MuAbort = True;
  2309.     cout << "Computation aborted by operator!\n\n";
  2310.   }
  2311.   if (Ch == ' ') {
  2312.     SoftAbort = True;
  2313.     cout << "SoftAbort flag set by operator!\n\n";
  2314.   }
  2315. } // --end-- MuInterrupt()
  2316.  
  2317. // ------- Get the value of the Dos clock in total seconds
  2318. double DosClock() {
  2319. // Only good to 0.01 seconds, must call earlier once each day
  2320.   double DC; // Local value of DosClock
  2321.   struct  time t;
  2322.   gettime( &t);
  2323.   DC = DosDays * 86400.0 + t.ti_hour * 3600.0
  2324.        + t.ti_min * 60.0 + t.ti_sec + t.ti_hund / 100.0;
  2325.   if (DC < DosClockP) {
  2326.     DosDays++;  DC += 86400.0;
  2327.   }
  2328.   DosClockP = DC;
  2329.   return DC;
  2330. } // --end-- DosClock
  2331.  
  2332. // ------- Save start time of a "Time-Out" period not to be timed
  2333. void TimeOut()
  2334. {
  2335.   if (DiagOn)  TV3 = DosClock();
  2336. } // --end-- // TimeOut
  2337.  
  2338. // ------- Adjust TV1 time at end of a "Time-Out" period not to be timed
  2339. void TimeIn()
  2340. {
  2341.   if (DiagOn)  TV2 += DosClock() - TV3;
  2342. } // --end-- // TimeIn
  2343.  
  2344. // ------- Output a diagnostic message with delta times
  2345. void Diag( char *Mess)
  2346. {
  2347.   if (DiagOn) {
  2348.     TV1 = TV2;  TV2 = DosClock();
  2349.     Del0 = TV2 - TV0;
  2350.     Del1 = TV2 - TV1;
  2351.     cout << "T = " << Del0 << "  DT = " << Del1 << " sec.";
  2352.     if (Mess[0])  cout << "  " << Mess;
  2353.     cout << nL;
  2354.     DiagL( LogF, Mess);
  2355.   }
  2356. } // --end-- // Diag
  2357.  
  2358. // ------- Log output of diagnostic message with delta times
  2359. void DiagL( ostream& LogF, char *Mess)
  2360. {
  2361.   if (DiagOn && LogF.good()) {
  2362.     LogF << "T = " << Del0 << "  DT = " << Del1 << " sec.";
  2363.     if (Mess[0])  LogF << "  " << Mess;
  2364.     LogF << nL;
  2365.   }
  2366. } // --end-- // DiagL
  2367.  
  2368. // ------- overloaded + infix add operator for MultiSI
  2369. MultiSI MultiSI::operator+ (MultiSI& X) {
  2370.   MultiSI T(1 + max( this->N, X.N)); // Temp variable
  2371.   T.Add( *this, X);
  2372.   ProtV = T.V; // Prevent T.V from being freed
  2373.   return T;
  2374. }
  2375. // & not allowed on return type because got error: attempting
  2376. //   to return a reference to a variable 'T'
  2377.  
  2378. // ------- overloaded - infix sub operator for MultiSI
  2379. MultiSI MultiSI::operator- (MultiSI& X) {
  2380.   MultiSI T(1 + max( this->N, X.N));
  2381.   T.Sub( *this, X);
  2382.   ProtV = T.V;  return T;
  2383. }
  2384.  
  2385. // ------- overloaded * infix mul operator for MultiSI
  2386. MultiSI MultiSI::operator* (MultiSI& X) {
  2387.   MultiSI T( this->N + X.N);
  2388.   T.Mul( *this, X);
  2389.   ProtV = T.V;  return T;
  2390. }
  2391.  
  2392. // ------- overloaded / infix div operator for MultiSI
  2393. MultiSI MultiSI::operator/ (MultiSI& X) {
  2394.   MultiSI T( this->N);
  2395.   T.Divi( *this, X);
  2396.   ProtV = T.V;  return T;
  2397. }
  2398.  
  2399. // ------- overloaded % infix mod operator for MultiSI
  2400. MultiSI MultiSI::operator% (MultiSI& X) {
  2401.   MultiSI T(X.N);
  2402.   T.Modu( *this, X);
  2403.   ProtV = T.V;  return T;
  2404. }
  2405.  
  2406. // ------- overloaded ^ infix xor operator, -> power
  2407.   MultiSI MultiSI::operator^ (MultiSI& X) {
  2408.   long n;
  2409.  
  2410.   if (~MuMB)  n = MuMB.N;
  2411.   else {
  2412.     MultiSI NN(9), Max(2);
  2413.     NN <<= this->N;
  2414.     NN <<= NN * X;
  2415.     Max <<= MMax;
  2416.     if (NN >= Max)  n = MMax;
  2417.     else
  2418.       n <<= NN;
  2419.   }
  2420.   MultiSI T(n);
  2421.   T.PowMB( *this, X);
  2422.   ProtV = T.V;  return T;
  2423. }
  2424.  
  2425. // ------- overloaded ^ infix xor operator, -> power
  2426.   MultiSI MultiSI::operator^ (double p) {
  2427.   MultiSI X(2);
  2428.   double d;
  2429.   long n;
  2430.  
  2431.   X.SetToD(p);
  2432.   if (~MuMB)  n = MuMB.N;
  2433.   else {
  2434.     d = this->N * p;
  2435.     if (d >= MMax)  n = MMax;
  2436.     else  n = (long) d;
  2437.   }
  2438.   MultiSI T(n);
  2439.   T.PowMB( *this, X);
  2440.   ProtV = T.V;  return T;
  2441. }
  2442.  
  2443. // ------- overloaded - unary minus operator for MultiSI
  2444. MultiSI MultiSI::operator- () {
  2445.   MultiSI T( this->N);
  2446.   T.SetTo( *this);  T.ChS();
  2447.   ProtV = T.V;  return T;
  2448. }
  2449.  
  2450. // ------- Output Date and time output stream
  2451. void OutDateTime(ostream& Out) {
  2452.   Out.fill('0');
  2453.   Out << setw(4) << da.da_year << '-'
  2454.       << setw(2) << (int)da.da_mon << '-'
  2455.       << setw(2) << (int)da.da_day << ' '
  2456.       << setw(2) << (int)ti.ti_hour << ':'
  2457.       << setw(2) << (int)ti.ti_min << ':'
  2458.       << setw(2) << (int)ti.ti_sec << '.'
  2459.       << setw(2) << (int)ti.ti_hund << nL;
  2460. } // --end-- OutDateTime
  2461.  
  2462. // ------- Get Date and time
  2463. void GetDateTime() {
  2464.   gettime(&ti);  getdate(&da);
  2465. } // --end-- GetDateTime
  2466.  
  2467. // ------- Initialize Multi-precision package
  2468. void InitMulti() {
  2469. // Input: MuDMax, MuNMax
  2470. // Output: Base, BaseSq, MaxDigit, BSMB, Pi, Pi2
  2471. // Initialize: MuDpG=5, MuLenD=21, MuErr=False, MuErrRep=True, MuAbort=False,
  2472. // Echo=0, MMax=MuNMax,  TracN=0, Trace=0, DiagOn=False, TV0=TV1=TV2=DosClock,
  2473. // MuDOnly=False
  2474.   GetDateTime();
  2475.   Base = 10;
  2476.   for (int i = 2; i <= MuDMax; i++)  Base *= 10;
  2477.   MaxDigit = Base - 1;
  2478.   BaseSq   = Base * Base;
  2479.   BSMB     = BaseSq - Base;
  2480.   Pi       = atan2l(0.0, -1.0);
  2481.   Pi2      = Pi + Pi;
  2482.   MuDpG    = 5;
  2483.   MuDOnly  = False;
  2484.   MuLenD   = 21;
  2485.   MuErr    = False;
  2486.   MuErrRep = True;
  2487.   MuAbort  = False;
  2488.   SoftAbort= False;
  2489.   KeyHit   = False;
  2490.   KeyCh    = ' ';
  2491.   Echo     = 0;
  2492.   MMax     = MuNMax;
  2493.   TracN    = 0;
  2494.   Trace    = 0;
  2495.   ShortN   = 0;
  2496.   DiagOn   = False;
  2497.   DosClockP= 86400.0;
  2498.   DosDays  = 0;
  2499.   MuMaxW   = 65;
  2500.   MuTot    = 0;
  2501.   ProtV    = NULL;
  2502.   Disk.close();
  2503.   LogF.close();
  2504.   TV3 = TV2 = TV1 = TV0 = DosClock();
  2505. //cout.setf( 0x1000 /*fixed*/);  cout.precision( 20); ???
  2506. //  ostream& Out = cout; // This worked
  2507. //  OutP[0]  = cout;  // OutP[i] << i << nL;  // a.WritLn( OutP[i]);
  2508. //  OutP[1]  = cLog;  // This did not work:
  2509. //  Error 'ios::operator =(ios near&)' is not accessible in function
  2510. //     ostream::operator =(ostream near&)
  2511. } // --end-- InitMulti Initialize Multi-precision package
  2512.  
  2513. // --end-- Other services
  2514.  
  2515. // Revisions made -
  2516. // Fixed an error in ReadSI: 
  2517. //    if ((Li = M - N) < 0) // HJS 1992-12-13 (was <= 0)
  2518. //      { OverFlow = True;  N = M;  Li = 0;  SDig = 0;  break; }
  2519.  
  2520. // --end-- MultiIDW.Cpp Multiple-precision integer decimal algorithms
  2521.